home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-03-27 | 127.5 KB | 2,757 lines | [TEXT/ROSA] |
- Common Lisp the Language, 2nd Edition
- -------------------------------------------------------------------------------
-
- 23. File System Interface
-
- A frequent use of streams is to communicate with a file system to which groups
- of data (files) can be written and from which files can be retrieved.
-
- Common Lisp defines a standard interface for dealing with such a file system.
- This interface is designed to be simple and general enough to accommodate the
- facilities provided by ``typical'' operating system environments within which
- Common Lisp is likely to be implemented. The goal is to make Common Lisp
- programs that perform only simple operations on files reasonably portable.
-
- To this end, Common Lisp assumes that files are named, that given a name one
- can construct a stream connected to a file of that name, and that the names can
- be fit into a certain canonical, implementation-independent form called a
- pathname.
-
- Facilities are provided for manipulating pathnames, for creating streams
- connected to files, and for manipulating the file system through pathnames and
- streams.
-
- -------------------------------------------------------------------------------
-
- * File Names
- o Pathnames
- o Case Conventions
- o Structured Directories
- o Extended Wildcards
- o Logical Pathnames
- + Syntax of Logical Pathname Namestrings
- + Parsing of Logical Pathname Namestrings
- + Using Logical Pathnames
- + Examples of the Use of Logical Pathnames
- + Discussion of Logical Pathnames
- o Pathname Functions
- * Opening and Closing Files
- * Renaming, Deleting, and Other File Operations
- * Loading Files
- * Accessing Directories
-
- -------------------------------------------------------------------------------
-
- 23.1. File Names
-
- Common Lisp programs need to use names to designate files. The main difficulty
- in dealing with names of files is that different file systems have different
- naming formats for files. For example, here is a table of several file systems
- (actually, operating systems that provide file systems) and what equivalent
- file names might look like for each one:
-
- System File Name
- ==================================================
- TOPS-20 <LISPIO>FORMAT.FASL.13
- TOPS-10 FORMAT.FAS[1,4]
- ITS LISPIO;FORMAT FASL
- MULTICS >udd>LispIO>format.fasl
- TENEX <LISPIO>FORMAT.FASL;13
- VAX/VMS [LISPIO]FORMAT.FAS;13
- UNIX /usr/lispio/format.fasl
- ==================================================
-
- It would be impossible for each program that deals with file names to know
- about each different file name format that exists; a new Common Lisp
- implementation might use a format different from any of its predecessors.
- Therefore, Common Lisp provides two ways to represent file names: namestrings,
- which are strings in the implementation-dependent form customary for the file
- system, and pathnames, which are special abstract data objects that represent
- file names in an implementation-independent way. Functions are provided to
- convert between these two representations, and all manipulations of files can
- be expressed in machine-independent terms by using pathnames.
-
- In order to allow Common Lisp programs to operate in a network environment that
- may have more than one kind of file system, the pathname facility allows a file
- name to specify which file system is to be used. In this context, each file
- system is called a host, in keeping with the usual networking terminology.
-
- [change_begin]
- Different hosts may use different notations for file names. Common Lisp allows
- customary notation to be used for each host, but also supports a system of
- logical pathnames that provides a standard framework for naming files in a
- portable manner (see section 23.1.5).
- [change_end]
-
- -------------------------------------------------------------------------------
-
- * Pathnames
- * Case Conventions
- * Structured Directories
- * Extended Wildcards
- * Logical Pathnames
- o Syntax of Logical Pathname Namestrings
- o Parsing of Logical Pathname Namestrings
- o Using Logical Pathnames
- o Examples of the Use of Logical Pathnames
- o Discussion of Logical Pathnames
- * Pathname Functions
-
- -------------------------------------------------------------------------------
-
- 23.1.1. Pathnames
-
- All file systems dealt with by Common Lisp are forced into a common framework,
- in which files are named by a Lisp data object of type pathname.
-
- A pathname always has six components, described below. These components are the
- common interface that allows programs to work the same way with different file
- systems; the mapping of the pathname components into the concepts peculiar to
- each file system is taken care of by the Common Lisp implementation.
-
- host
- The name of the file system on which the file resides.
-
- device
- Corresponds to the ``device'' or ``file structure'' concept in many host
- file systems: the name of a (logical or physical) device containing files.
-
- directory
- Corresponds to the ``directory'' concept in many host file systems: the
- name of a group of related files (typically those belonging to a single
- user or project).
-
- name
- The name of a group of files that can be thought of as the ``same'' file.
-
- type
- Corresponds to the ``filetype'' or ``extension'' concept in many host file
- systems; identifies the type of file. Files with the same names but
- different types are usually related in some specific way, for instance,
- one being a source file, another the compiled form of that source, and a
- third the listing of error messages from the compiler.
-
- version
- Corresponds to the ``version number'' concept in many host file systems.
- Typically this is a number that is incremented every time the file is
- modified.
-
- Note that a pathname is not necessarily the name of a specific file. Rather, it
- is a specification (possibly only a partial specification) of how to access a
- file. A pathname need not correspond to any file that actually exists, and more
- than one pathname can refer to the same file. For example, the pathname with a
- version of ``newest'' may refer to the same file as a pathname with the same
- components except a certain number as the version. Indeed, a pathname with
- version ``newest'' may refer to different files as time passes, because the
- meaning of such a pathname depends on the state of the file system. In file
- systems with such facilities as ``links,'' multiple file names, logical
- devices, and so on, two pathnames that look quite different may turn out to
- address the same file. To access a file given a pathname, one must do a file
- system operation such as open.
-
- Two important operations involving pathnames are parsing and merging. Parsing
- is the conversion of a namestring (which might be something supplied
- interactively by the user when asked to supply the name of a file) into a
- pathname object. This operation is implementation-dependent, because the format
- of namestrings is implementation-dependent. Merging takes a pathname with
- missing components and supplies values for those components from a source of
- defaults.
-
- Not all of the components of a pathname need to be specified. If a component of
- a pathname is missing, its value is nil. Before the file system interface can
- do anything interesting with a file, such as opening the file, all the missing
- components of a pathname must be filled in (typically from a set of defaults).
- Pathnames with missing components may be used internally for various purposes;
- in particular, parsing a namestring that does not specify certain components
- will result in a pathname with missing components.
-
- [change_begin]
- X3J13 voted in January 1989 (PATHNAME-UNSPECIFIC-COMPONENT) to permit any
- component of a pathname to have the value :unspecific, meaning that the
- component simply does not exist, for file systems in which such a value makes
- sense. (For example, a UNIX file system usually does not support version
- numbers, so the version component of a pathname for a UNIX host might be
- :unspecific. Similarly, the file type is usually regarded in a UNIX file system
- as the part of a name after a period, but some file names contain no periods
- and therefore have no file types.)
-
- When a pathname is converted to a namestring, the values nil and :unspecific
- have the same effect: they are treated as if the component were empty (that is,
- they each cause the component not to appear in the namestring). When merging,
- however, only a nil value for a component will be replaced with the default for
- that component; the value :unspecific will be left alone as if the field were
- filled.
-
- The results are undefined if :unspecific is supplied to a file system in a
- component for which :unspecific does not make sense for that file system.
-
- Programming hint: portable programs should be prepared to handle the value
- :unspecific in the device, directory, type, or version field in some
- implementations. Portable programs should not explicitly place :unspecific in
- any field because it might not be permitted in some situations, but portable
- programs may sometimes do so implicitly (by copying such a value from another
- pathname, for example).
- [change_end]
-
- [old_change_begin]
- A component of a pathname can also be the keyword :wild. This is only useful
- when the pathname is being used with a directory-manipulating operation, where
- it means that the pathname component matches anything. The printed
- representation of a pathname typically designates :wild by an asterisk;
- however, this is host-dependent.
- [old_change_end]
-
- See section 23.1.4 for a discussion of new wildcard pathname facilities.
-
- What values are allowed for components of a pathname depends, in general, on
- the pathname's host. However, in order for pathnames to be usable in a
- system-independent way, certain global conventions are adhered to. These
- conventions are stronger for the type and version than for the other
- components, since the type and version are explicitly manipulated by many
- programs, while the other components are usually treated as something supplied
- by the user that just needs to be remembered and copied from place to place.
-
- The type is always a string or nil or :wild. It is expected that most programs
- that deal with files will supply a default type for each file.
-
- The version is either a positive integer or a special symbol. The meanings of
- nil and :wild have been explained above. The keyword :newest refers to the
- largest version number that already exists in the file system when reading a
- file, or to a version number greater than any already existing in the file
- system when writing a new file. Some Common Lisp implementors may choose to
- define other special version symbols. Some semi-standard names, suggested but
- not required to be supported by every Common Lisp implementation, are :oldest,
- to refer to the smallest version number that exists in the file system;
- :previous, to refer to the version previous to the newest version; and
- :installed, to refer to a version that is officially installed for users (as
- opposed to a working or development version). Some Common Lisp implementors may
- also choose to attach a meaning to non-positive version numbers (a typical
- convention is that 0 is synonymous with :newest and -1 with :previous), but
- such interpretations are implementation-dependent.
-
- The host may be a string, indicating a file system, or a list of strings, of
- which the first names the file system and the rest may be used for such a
- purpose as inter-network routing.
-
- [old_change_begin]
- The device, directory, and name can each be a string (with host-dependent rules
- on allowed characters and length) or possibly some other Common Lisp data
- structure (in which case such a component is said to be structured and has an
- implementation-dependent format). Structured components may be used to handle
- such file system features as hierarchical directories. Common Lisp programs do
- not need to know about structured components unless they do host-dependent
- operations. Specifying a string as a pathname component for a host that
- requires a structured component will cause conversion of the string to the
- appropriate form.
- [old_change_end]
-
- [change_begin]
- X3J13 voted in June 1989 (PATHNAME-SUBDIRECTORY-LIST) to define a specific
- format for structured directories (see section 23.1.3).
-
- X3J13 voted in June 1989 (PATHNAME-COMPONENT-VALUE) to approve the following
- clarifications and specifications of precisely what are valid values for the
- various components of a pathname.
-
- Pathname component value strings never contain the punctuation characters that
- are used to separate fields in a namestring (for example, slashes and periods
- as used in UNIX file systems). Punctuation characters appear only in
- namestrings. Characters used as punctuation can appear in pathname component
- values with a non-punctuation meaning if the file system allows it (for
- example, UNIX file systems allow a file name to begin with a period).
-
- When examining pathname components, conforming programs must be prepared to
- encounter any of the following siutations:
-
- * Any component can be nil, which means the component has not been
- specified.
-
- * Any component can be :unspecific, which means the component has no
- meaning in this particular pathname.
-
- * The device, directory, name, and type can be strings.
-
- * The host can be any object, at the discretion of the implementation.
-
- * The directory can be a list of strings and symbols as described in
- section 23.1.3.
-
- * The version can be any symbol or any integer. The symbol :newest refers
- to the largest version number that already exists in the file system when
- reading, overwriting, appending, superseding, or directory-listing an
- existing file; it refers to the smallest version number greater than any
- existing version number when creating a new file. Other symbols and
- integers have implementation-defined meaning. It is suggested, but not
- required, that implementations use positive integers starting at 1 as
- version numbers, recognize the symbol :oldest to designate the smallest
- existing version number, and use keyword symbols for other special
- versions.
-
- When examining wildcard components of a wildcard pathname, conforming programs
- must be prepared to encounter any of the following additional values in any
- component or any element of a list that is the directory component:
-
- * The symbol :wild, which matches anything.
-
- * A string containing implementation-dependent special wildcard characters.
-
- * Any object, representing an implementation-dependent wildcard pattern.
-
- When constructing a pathname from components, conforming programs must follow
- these rules:
-
- * Any component may be nil. Specifying nil for the host may, in some
- implementations, result in using a default host rather than an actual nil
- value.
-
- * The host, device, directory, name, and type may be strings. There are
- implementation-dependent limits on the number and type of characters in
- these strings. A plausible assumption is that letters (of a single case)
- and digits are acceptable to most file systems.
-
-
- section 23.1.3. There are implementation-dependent limits on the length
- and contents of the list.
-
- * The version may be :newest.
-
- * Any component may be taken from the corresponding component of another
- pathname. When the two pathnames are for different file systems (in
- implementations that support multiple file systems), an appropriate
- translation occurs. If no meaningful translation is possible, an error is
- signaled. The definitions of ``appropriate'' and ``meaningful'' are
- implementation-dependent.
-
- * When constructing a wildcard pathname, the name, type, or version may be
- :wild, which matches anything.
-
- * An implementation might support other values for some components, but a
- portable program should not use those values. A conforming program can use
- implementation-dependent values but this can make it non-portable; for
- example, it might work only with UNIX file systems.
-
- [change_end]
-
- The best way to compare two pathnames for equality is with equal, not eql. (On
- pathnames, eql is simply the same as eq.) Two pathname objects are equal if and
- only if all the corresponding components (host, device, and so on) are
- equivalent. (Whether or not uppercase and lowercase letters are considered
- equivalent in strings appearing in components depends on the file name
- conventions of the file system.) Pathnames that are equal should be
- functionally equivalent.
-
- [old_change_begin]
- Some host file systems have features that do not fit into this pathname model.
- For instance, directories might be accessible as files; there might be
- complicated structure in the directories or names; or there might be a way to
- specify a directory relative to a ``current'' directory, such as the < syntax
- in MULTICS or the special ``..'' file name of UNIX. Such features are not
- allowed for by the standard Common Lisp file system interface. An
- implementation is free to accommodate such features in its pathname
- representation and provide a parser that can process such specifications in
- namestrings; such features are then likely to work within that single
- implementation. However, note that once a program depends explicitly on any
- such features, it will not be portable.
- [old_change_end]
-
- [change_begin]
- X3J13 voted in June 1989 (PATHNAME-SUBDIRECTORY-LIST) to define a specific
- format for structured directories (see section 23.1.3), so some of the specific
- examples in the previous paragraph no longer apply, but the principle is still
- correct.
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 23.1.2. Case Conventions
-
- [change_begin]
- Issues of alphabetic case in pathnames are a major source of problems. In some
- file systems, the customary case is lowercase, in some uppercase, in some
- mixed. Some file systems are case-sensitive (that is, they treat FOO and foo as
- different file names) and others are not.
-
- There are two kinds of pathname case portability problems: moving programs from
- one Common Lisp to another, and moving pathname component values from one file
- system to another. The solution to the first problem is the requirement that
- all Common Lisp implementations that support a particular file system must use
- compatible representations for pathname component values. The solution to the
- second problem is the use of a common representation for the
- least-common-denominator pathname component values that exist on all
- interesting file systems.
-
- Requiring a common representation directly conflicts with the desire among
- programmers that use only one file system to work with the local conventions
- and to ignore issues of porting to other file systems. The common
- representation cannot be the same as local (varying) conventions.
-
- X3J13 voted in June 1989 (PATHNAME-COMPONENT-CASE) to add a keyword argument
- :case to each of the functions make-pathname, pathname-host, pathname-device,
- pathname-directory, pathname-name, and pathname-type. The possible values for
- the argument are :common and :local. The default is :local.
-
- The value :local means that strings given to make-pathname or returned by any
- of the pathname component accessors follow the local file system's conventions
- for alphabetic case. Strings given to make-pathname will be used exactly as
- written if the file system supports both cases. If the file system supports
- only one case, the strings will be translated to that case.
-
- The value :common means that strings given to make-pathname or returned by any
- of the pathname component accessors follow this common convention:
-
- * All uppercase means that a file system's customary case will be used.
- * All lowercase means that the opposite of the customary case will be used.
- * Mixed case represents itself.
-
- Uppercase is used as the common case for no better reason than consistency with
- Lisp symbols. The second and third points allow translation from local
- representation to common and back to be information-preserving. (Note that
- translation from common to local representation and back may or may not be
- information-preserving, depending on the nature of the local representation.)
-
- Namestrings always use :local file system case conventions.
-
- Finally, merge-pathnames and translate-pathname map customary case in the input
- pathnames into customary case in the output pathname.
-
- Examples of possible use of this convention:
-
- * TOPS-20 is case-sensitive and prefers uppercase, translating lowercase to
- uppercase unless escaped with ^V; for a TOPS-20-based file system, a
- Common Lisp implementation should use identical representations for common
- and local.
-
- * UNIX is case-sensitive and prefers lowercase; for a UNIX-based file
- system, a Common Lisp implementation should translate between common and
- local representations by inverting the case of non-mixed-case strings.
-
- * VAX/VMS is uppercase-only (that is, the file system translates all file
- name arguments to uppercase); for a VAX/VMS-based file system, a Common
- Lisp implementation should translate common representation to local by
- converting to uppercase and should translate local representation to
- common with no change.
-
- * The Macintosh operating system is case-insensitive and prefers lowercase,
- but remembers the cases of letters actually used to name a file; for a
- Macintosh-based file system, a Common Lisp implementation should translate
- between common and local representations by inverting the case of
- non-mixed-case strings and should ignore case when determining whether two
- pathnames are equal.
-
- Here are some examples of this behavior. Assume that the host T runs TOPS-20, U
- runs UNIX, V runs VAX/VMS, and M runs the Macintosh operating system.
-
- ;;; Returns two values: the PATHNAME-NAME from a namestring
- ;;; in :COMMON and :LOCAL representations (in that order).
- (defun pathname-example (name)
- (let ((path (parse-namestring name))))
- (values (pathname-name path :case :common)
- (pathname-name path :case :local))))
-
- => "FOO" and Ø"FOO" ;Common Local
- (pathname-example "T:<ME>FOO.LISP") => "FOO" and "FOO"
- (pathname-example "T:<ME>foo.LISP") => "FOO" and "FOO"
- (pathname-example "T:<ME>^Vf^Vo^Vo.LISP") => "foo" and "foo"
- (pathname-example "T:<ME>TeX.LISP") => "TEX" and "TEX"
- (pathname-example "T:<ME>T^VeX.LISP") => "TeX" and "TeX"
- (pathname-example "U:/me/FOO.lisp") => "foo" and "FOO"
- (pathname-example "U:/me/foo.lisp") => "FOO" and "foo"
- (pathname-example "U:/me/TeX.lisp") => "TeX" and "TeX"
- (pathname-example "V:[me]FOO.LISP") => "FOO" and "FOO"
- (pathname-example "V:[me]foo.LISP") => "FOO" and "FOO"
- (pathname-example "V:[me]TeX.LISP") => "TEX" and "TEX"
- (pathname-example "M:FOO.LISP") => "foo" and "FOO"
- (pathname-example "M:foo.LISP") => "FOO" and "foo"
- (pathname-example "M:TeX.LISP") => "TeX" and "TeX"
-
- The following example illustrates the creation of new pathnames. The name is
- converted from common representation to local because namestrings always use
- local conventions.
-
- (defun make-pathname-example (h n)
- (namestring (make-pathname :host h :name n :case :common))
-
- (make-pathname-example "T" "FOO") => "T:FOO"
- (make-pathname-example "T" "foo") => "T:^Vf^Vo^Vo"
- (make-pathname-example "T" "TeX") => "T:T^VeX"
- (make-pathname-example "U" "FOO") => "U:foo"
- (make-pathname-example "U" "foo") => "U:FOO"
- (make-pathname-example "U" "TeX") => "U:TeX"
- (make-pathname-example "V" "FOO") => "V:FOO"
- (make-pathname-example "V" "foo") => "V:FOO"
- (make-pathname-example "V" "TeX") => "V:TeX"
- (make-pathname-example "M" "FOO") => "M:foo"
- (make-pathname-example "M" "foo") => "M:FOO"
- (make-pathname-example "M" "TeX") => "M:TeX"
-
- A big advantage of this set of conventions is that one can, for example, call
- make-pathname with :type "LISP" and :case :common, and the result will appear
- in a namestring as .LISP or .lisp, whichever is appropriate.
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 23.1.3. Structured Directories
-
- [change_begin]
- X3J13 voted in June 1989 (PATHNAME-SUBDIRECTORY-LIST) to define a specific
- pathname component format for structured directories.
-
- The value of a pathname's directory component may be a list. The car of the
- list should be a keyword, either :absolute or :relative. Each remaining element
- of the list should be a string or a symbol (see below). Each string names a
- single level of directory structure and should consist of only the directory
- name without any punctuation characters.
-
- A list whose car is the symbol :absolute represents a directory path starting
- from the root directory. For example, the list (:absolute) represents the root
- directory itself; the list (:absolute "foo" "bar" "baz") represents the
- directory that in a UNIX file system would be called /foo/bar/baz.
-
- A list whose car is the symbol :relative represents a directory path starting
- from a default directory. The list (:relative) has the same meaning as nil and
- hence normally is not used. The list (:relative "foo" "bar") represents the
- directory named bar in the directory named foo in the default directory.
-
- In place of a string, at any point in the list, a symbol may occur to indicate
- a special file notation. The following symbols have standard meanings.
-
- :wild
- Wildcard match of one level of directory structure
- :wild-inferiors
- Wildcard match of any number of directory levels
- :up Go upward in directory structure (semantic)
- :back
- Go upward in directory structure (syntactic)
-
- (See section 23.1.4 for a discussion of wildcard pathnames.)
-
- Implementations are permitted to add additional objects of any non-string type
- if necessary to represent features of their file systems that cannot be
- represented with the standard strings and symbols. Supplying any non-string,
- including any of the symbols listed below, to a file system for which it does
- not make sense signals an error of type file-error. For example, most
- implementations of the UNIX file system do not support :wild-inferiors. Any
- directory list in which :absolute or :wild-inferiors is immediately followed by
- :up or :back is illegal and when processed causes an error to be signaled.
-
- The keyword :back has a ``syntactic'' meaning that depends only on the pathname
- and not on the contents of the file system. The keyword :up has a ``semantic''
- meaning that depends on the contents of the file system; to resolve a pathname
- containing :up to a pathname whose directory component contains only :absolute
- and strings requires a search of the file system. Note that use of :up instead
- of :back can result in designating a different actual directory only in file
- systems that support multiple names for directories, perhaps via symbolic
- links. For example, suppose that there is a directory link such that
-
- (:absolute "X" "Y") is linked to (:absolute "A" "B")
-
- and there also exist directories
-
- (:absolute "A" "Q") and (:absolute "X" "Q")
-
- Then
-
- (:absolute "X" "Y" :up "Q") designates (:absolute "A" "Q")
-
- but
-
- (:absolute "X" "Y" :back "Q") designates (:absolute "X" "Q")
-
- If a string is used as the value of the :directory argument to make-pathname,
- it should be the name of a top-level directory and should not contain any
- punctuation characters. Specifying a string s is equivalent to specifying the
- list (:absolute s). Specifying the symbol :wild is equivalent to specifying the
- list (:absolute :wild-inferiors) (or (:absolute :wild) in a file system that
- does not support :wild-inferiors).
-
- The function pathname-directory always returns nil, :unspecific, or a
- list-never a string, never :wild. If a list is returned, it is not guaranteed
- to be freshly consed; the consequences of modifying this list are undefined.
-
- In non-hierarchical file systems, the only valid list values for the directory
- component of a pathname are (:absolute s) (where s is a string) and (:absolute
- :wild). The keywords :relative, :wild-inferiors, :up, and :back are not used in
- non-hierarchical file systems.
-
- Pathname merging treats a relative directory specially. Let pathname and
- defaults be the first two arguments to merge-pathnames. If (pathname-directory
- pathname) is a list whose car is :relative, and (pathname-directory defaults)
- is a list, then the merged directory is the value of
-
- (append (pathname-directory defaults)
- (cdr ;Remove :relative from the front
- (pathname-directory pathname)))
-
- except that if the resulting list contains a string or :wild immediately
- followed by :back, both of them are removed. This removal of redundant
- occurrences of :back is repeated as many times as possible. If
- (pathname-directory defaults) is not a list or (pathname-directory pathname) is
- not a list whose car is :relative, the merged directory is the value of
-
- (or (pathname-directory pathname)
- (pathname-directory defaults))
-
- A relative directory in the pathname argument to a function such as open is
- merged with the value of *default-pathname-defaults* before the file system is
- accessed.
-
- Here are some examples of the use of structured directories. Suppose that host
- L supports a Symbolics Lisp Machine file system, host U supports a UNIX file
- system, and host V supports a VAX/VMS file system.
-
- (pathname-directory (parse-namestring "V:[FOO.BAR]BAZ.LSP"))
- => (:ABSOLUTE "FOO" "BAR")
-
- (pathname-directory (parse-namestring "U:/foo/bar/baz.lisp"))
- => (:ABSOLUTE "foo" "bar")
-
- (pathname-directory (parse-namestring "U:../baz.lisp"))
- => (:RELATIVE :UP)
-
- (pathname-directory (parse-namestring "U:/foo/bar/../mum/baz"))
- => (:ABSOLUTE "foo" "bar" :UP "mum")
-
- (pathname-directory (parse-namestring "U:bar/../../ztesch/zip"))
- => (:RELATIVE "bar" :UP :UP "ztesch")
-
- (pathname-directory (parse-namestring "L:>foo>**>bar>baz.lisp"))
- => (:ABSOLUTE "FOO" :WILD-INFERIORS "BAR")
-
- (pathname-directory (parse-namestring "L:>foo>*>bar>baz.lisp"))
- => (:ABSOLUTE "FOO" :WILD "BAR")
-
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 23.1.4. Extended Wildcards
-
- [change_begin]
- Some file systems provide more complex conventions for wildcards than simple
- component-wise wildcards representable by :wild. For example, the namestring
- "F*O" might mean a normal three-character name; a three-character name with the
- middle character wild; a name with at least two characters, beginning with F
- and ending with O; or perhaps a wild match spanning multiple directories.
- Similarly, the namestring ">foo>**>bar>" might imply that the middle directory
- is named "**"; the middle directory is :wild; there are zero or more middle
- directories that are :wild; or perhaps that the middle directory name matches
- any two-letter name. Some file systems support even more complex wildcards,
- such as regular expressions.
-
- X3J13 voted in June 1989 (PATHNAME-WILD) to provide some facilities for
- dealing with more general wildcard pathnames in a fairly portable manner.
-
- [Function]
- wild-pathname-p pathname &optional field-key
-
- Tests a pathname for the presence of wildcard components. If the first argument
- is not a pathname, string, or file stream, an error of type type-error is
- signaled.
-
- If no field-key is provided, or the field-key is nil, the result is true if and
- only if pathname has any wildcard components.
-
- If a non-null field-key is provided, it must be one of :host, :device,
- :directory, :name, :type, or :version. In this case, the result is true if and
- only if the indicated component of pathname is a wildcard.
-
- Note that X3J13 voted in June 1989 (PATHNAME-COMPONENT-VALUE) to specify that
- an implementation need not support wildcards in all fields; the only
- requirement is that the name, type, or version may be :wild. However, portable
- programs should be prepared to encounter either :wild or
- implementation-dependent wildcards in any pathname component. The function
- wild-pathname-p provides a portable way for testing the presence of wildcards.
-
- [Function]
- pathname-match-p pathname wildname
-
- This predicate is true if and only if the pathname matches the wildname. The
- matching rules are implementation-defined but should be consistent with the
- behavior of the directory function. Missing components of wildname default to
- :wild.
-
- If either argument is not a pathname, string, or file stream, an error of type
- type-error is signaled. It is valid for pathname to be a wild pathname; a
- wildcard field in pathname will match only a wildcard field in wildname; that
- is, pathname-match-p is not commutative. It is valid for wildname to be a
- non-wild pathname; I believe that in this case pathname-match-p will have the
- same behavior as equal, though the X3J13 specification did not say so.
-
- [Function]
- translate-pathname source from-wildname to-wildname &key
-
- Translates the pathname source, which must match from-wildname, into a
- corresponding pathname (call it result), which is constructed so as to match
- to-wildname, and returns result.
-
- The pathname result is a copy of to-wildname with each missing or wildcard
- field replaced by a portion of source; for this purpose a wildcard field is a
- pathname component with a value of :wild, a :wild element of a list-valued
- directory component, or an implementation-defined portion of a component, such
- as the * in the complex wildcard string "foo*bar" that some implementations
- support. An implementation that adds other wildcard features, such as regular
- expressions, must define how translate-pathname extends to those features. A
- missing field is a pathname component that is nil.
-
- The portion of source that is copied into result is implementation-defined.
- Typically it is determined by the user interface conventions of the file
- systems involved. Usually it is the portion of source that matches a wildcard
- field of from-wildname that is in the same position as the missing or wildcard
- field of to-wildname. If there is no wildcard field in from-wildname at that
- position, then usually it is the entire corresponding pathname component of
- source or, in the case of a list-valued directory component, the entire
- corresponding list element. For example, if the name components of source,
- from-wildname, and to-wildname are "gazonk", "gaz*", and "h*" respectively,
- then in most file systems the wildcard fields of the name component of
- from-wildname and to-wildname are each "*", the matching portion of source is
- "onk", and the name component of result is "honk"; however, the exact behavior
- of translate-pathname is not dictated by the Common Lisp language and may vary
- according to the user interface conventions of the file systems involved.
-
- During the copying of a portion of source into result, additional
- implementation-defined translations of alphabetic case or file naming
- conventions may occur, especially when from-wildname and to-wildname are for
- different hosts.
-
- If any of the first three arguments is not a pathname, string, or file stream,
- an error of type type-error is signaled. It is valid for source to be a wild
- pathname; in general this will produce a wild result pathname. It is valid for
- from-wildname or to-wildname or both to be non-wild. An error is signaled if
- the source pathname does not match the from-wildname, that is, if
- (pathname-match-p source from-wildname) would not be true.
-
- There are no specified keyword arguments for translate-pathname, but
- implementations are permitted to extend it by adding keyword arguments. There
- is one specified return value from translate-pathname; implementations are
- permitted to extend it by returning additional values.
-
- Here is an implementation suggestion. One file system performs this operation
- by examining corresponding pieces of the three pathnames in turn, where a piece
- is a pathname component or a list element of a structured component such as a
- hierarchical directory. Hierarchical directory elements in from-wildname and
- to-wildname are matched by whether they are wildcards, not by depth in the
- directory hierarchy. If the piece in to-wildname is present and not wild, it is
- copied into the result. If the piece in to-wildname is :wild or nil, the
- corresponding piece in source is copied into the result. Otherwise, the piece
- in to-wildname might be a complex wildcard such as "foo*bar"; the portion of
- the piece in source that matches the wildcard portion of the corresponding
- piece in from-wildname (or the entire source piece, if the from-wildname piece
- is not wild and therefore equals the source piece) replaces the wildcard
- portion of the piece in to-wildname and the value produced is used in the
- result.
-
- X3J13 voted in June 1989 (PATHNAME-COMPONENT-CASE) to require
- translate-pathname to map customary case in argument pathnames to the customary
- case in returned pathnames (see section 23.1.2).
-
- Here are some examples of the use of the new wildcard pathname facilities.
- These examples are not portable. They are written to run with particular file
- systems and particular wildcard conventions and are intended to be
- illustrative, not prescriptive. Other implementations may behave differently.
-
- (wild-pathname-p (make-pathname :name :wild)) => t
- (wild-pathname-p (make-pathname :name :wild) :name) => t
- (wild-pathname-p (make-pathname :name :wild) :type) => nil
- (wild-pathname-p (pathname "S:>foo>**>")) => t ;Maybe
- (wild-pathname-p (make-pathname :name "F*O")) => t ;Probably
-
- One cannot rely on rename-file to handle wild pathnames in a predictable
- manner. However, one can use translate-pathname explicitly to control the
- process.
-
- (defun rename-files (from to)
- "Rename all files that match the first argument by
- translating their names to the form of the second
- argument. Both arguments may be wild pathnames."
- (dolist (file (directory from))
- ;; DIRECTORY produces only pathnames that match from-wildname.
- (rename-file file (translate-pathname file from to))))
-
- Assuming one particular set of popular wildcard conventions, this function
- might exhibit the following behavior. Not all file systems will run this
- example exactly as written.
-
- (rename-files "/usr/me/*.lisp" "/dev/her/*.l")
- renames /usr/me/init.lisp
- to /dev/her/init.l
-
- (rename-files "/usr/me/pcl*/*" "/sys/pcl/*/")
- renames /usr/me/pcl-5-may/low.lisp
- to /sys/pcl/pcl-5-may/low.lisp
- (in some file systems the result might be /sys/pcl/5-may/low.lisp)
-
- (rename-files "/usr/me/pcl*/*" "/sys/library/*/")
- renames /usr/me/pcl-5-may/low.lisp
- to /sys/library/pcl-5-may/low.lisp
- (in some file systems the result might be /sys/library/5-may/low.lisp)
-
- (rename-files "/usr/me/foo.bar" "/usr/me2/")
- renames /usr/me/foo.bar
- to /usr/me2/foo.bar
-
- (rename-files "/usr/joe/*-recipes.text"
- "/usr/jim/personal/cookbook/joe's-*-rec.text")
- renames /usr/joe/lamb-recipes.text
- to /usr/jim/personal/cookbook/joe's-lamb-rec.text
- renames /usr/joe/veg-recipes.text
- to /usr/jim/personal/cookbook/joe's-veg-rec.text
- renames /usr/joe/cajun-recipes.text
- to /usr/jim/personal/cookbook/joe's-cajun-rec.text
- renames /usr/joe/szechuan-recipes.text
- to /usr/jim/personal/cookbook/joe's-szechuan-rec.text
-
- The following examples use UNIX syntax and the wildcard conventions of one
- particular version of UNIX.
-
- (namestring
- (translate-pathname "/usr/dmr/hacks/frob.l"
- "/usr/d*/hacks/*.l"
- "/usr/d*/backup/hacks/backup-*.*"))
- => "/usr/dmr/backup/hacks/backup-frob.l"
-
- (namestring
- (translate-pathname "/usr/dmr/hacks/frob.l"
- "/usr/d*/hacks/fr*.l"
- "/usr/d*/backup/hacks/backup-*.*"))
- => "/usr/dmr/backup/hacks/backup-ob.l"
-
- The following examples are similar to the preceding examples but use two
- different hosts; host U supports a UNIX file system and host V supports a
- VAX/VMS file system. Note the translation of file type (from l to LSP) and the
- change of alphabetic case conventions.
-
- (namestring
- (translate-pathname "U:/usr/dmr/hacks/frob.l"
- "U:/usr/d*/hacks/*.l"
- "V:SYS$DISK:[D*.BACKUP.HACKS]BACKUP-*.*"))
- => "V:SYS$DISK:[DMR.BACKUP.HACKS]BACKUP-FROB.LSP"
-
- (namestring
- (translate-pathname "U:/usr/dmr/hacks/frob.l"
- "U:/usr/d*/hacks/fr*.l"
- "V:SYS$DISK:[D*.BACKUP.HACKS]BACKUP-*.*"))
- => "V:SYS$DISK:[DMR.BACKUP.HACKS]BACKUP-OB.LSP"
-
- The next example is a version of the function translate-logical-pathname
- (simplified a bit) for a logical host named FOO. The points of interest are the
- use of pathname-match-p as a :test argument for assoc and the use of
- translate-pathname as a substrate for translate-logical-pathname.
-
- (define-condition logical-translation-error (file-error))
-
- (defun my-translate-logical-pathname (pathname &key rules)
- (let ((rule (assoc pathname rules :test #'pathname-match-p)))
- (unless rule
- (error 'logical-translation-error :pathname pathname))
- (translate-pathname pathname (first rule) (second rule))))
-
- (my-translate-logical-pathname
- "FOO:CODE;BASIC.LISP"
- :rules '(("FOO:DOCUMENTATION;" "U:/doc/foo/")
- ("FOO:CODE;" "U:/lib/foo/")
- ("FOO:PATCHES;*;" "U:/lib/foo/patch/*/")))
- => #P"U:/lib/foo/basic.l"
-
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 23.1.5. Logical Pathnames
-
- [change_begin]
- Pathname values are not portable, but sometimes they must be mentioned in a
- program (for example, the names of files containing the program and the data
- used by the program).
-
- X3J13 voted in June 1989 (PATHNAME-LOGICAL) to provide some facilities for
- portable pathname values. The idea is to provide a portable framework for
- pathname values; these logical pathnames are then mapped to physical (that is,
- actual) pathnames by a set of implementation-dependent or site-dependent rules.
- The logical pathname facility therefore separates the concerns of program
- writing and user software architecture from the details of how a software
- system is embedded in a particular file system or operating environment.
-
- Pathname values are not portable because not all Common Lisp implementations
- use the same operating system and file name syntax varies widely among
- operating systems. In addition, corresponding files at two different sites may
- have different names even when the operating system is the same; for example,
- they may be on different directories or different devices. The Common Lisp
- logical pathname system defines a particular pathname structure and namestring
- syntax that must be supported by all implementations.
-
- [Class]
- logical-pathname
-
- This is a subclass of pathname.
- [change_end]
-
- -------------------------------------------------------------------------------
-
- * Syntax of Logical Pathname Namestrings
- * Parsing of Logical Pathname Namestrings
- * Using Logical Pathnames
- * Examples of the Use of Logical Pathnames
- * Discussion of Logical Pathnames
-
- -------------------------------------------------------------------------------
-
- 23.1.5.1. Syntax of Logical Pathname Namestrings
-
- [change_begin]
- The syntax of a logical pathname namestring is as follows:
-
- logical-namestring ::= [host :] [;] {directory ;}*
- [name] [. type [. version]
-
- Note that a logical namestring has no device portion.
-
- host ::= word
- directory ::= word | wildcard-word | wildcard-inferiors
- name ::= word | wildcard-word
- type ::= word | wildcard-word
- version ::= word | wildcard-word
- word ::= {letter digit -}+
- wildcard-word ::= [word] * {word *}* [word]
- wildcard-inferiors ::= **
-
- A word consists of one or more uppercase letters, digits, and hyphens.
-
- A wildcard word consists of one or more asterisks, uppercase letters, digits,
- and hyphens, including at least one asterisk, with no two asterisks adjacent.
- Each asterisk matches a sequence of zero or more characters. The wildcard word
- * parses as :wild; all others parse as strings.
-
- Lowercase letters may also appear in a word or wildcard word occurring in a
- namestring. Such letters are converted to uppercase when the namestring is
- converted to a pathname. The consequences of using other characters are
- unspecified.
-
- The host is a word that has been defined as a logical pathname host by using
- setf with the function logical-pathname-translations.
-
- There is no device, so the device component of a logical pathname is always
- :unspecific. No other component of a logical pathname can be :unspecific.
-
- Each directory is a word, a wildcard word, or ** (which is parsed as
- :wild-inferiors). If a semicolon precedes the directories, the directory
- component is relative; otherwise it is absolute.
-
- The name is a word or a wildcard word.
-
- The type is a word or a wildcard word.
-
- The version is a positive decimal integer or the word NEWEST (which is parsed
- as :newest) or * (which is parsed as :wild). The letters in NEWEST can be in
- either alphabetic case.
-
- The consequences of using any value not specified here as a logical pathname
- component are unspecified. The null string "" is not a valid value for any
- component of a logical pathname, since the null string is not a word or a
- wildcard word.
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 23.1.5.2. Parsing of Logical Pathname Namestrings
-
- [change_begin]
- Logical pathname namestrings are recognized by the functions logical-pathname
- and translate-logical-pathname. The host portion of the logical pathname
- namestring and its following colon must appear in the namestring arguments to
- these functions.
-
- The function parse-namestring recognizes a logical pathname namestring when the
- host argument is logical or the defaults argument is a logical pathname. In
- this case the host portion of the logical pathname namestring and its following
- colon are optional. If the host portion of the namestring and the host argument
- are both present and do not match, an error is signaled. The host argument is
- logical if it is supplied and came from pathname-host of a logical pathname.
- Whether a host argument is logical if it is a string equal to a logical
- pathname host name is implementation-defined.
-
- The function merge-pathnames recognizes a logical pathname namestring when the
- defaults argument is a logical pathname. In this case the host portion of the
- logical pathname namestring and its following colon are optional.
-
- Whether the other functions that coerce strings to pathnames recognize logical
- pathname namestrings is implementation-defined. These functions include
- parse-namestring in circumstances other than those described above,
- merge-pathnames in circumstances other than those described above, the
- :defaults argument to make-pathname, and the following functions:
-
- compile-file file-write-date pathname-name
- compile-file-pathname host-namestring pathname-type
- delete-file load pathname-version
- directory namestring probe-file
- directory-namestring open rename-file
- dribble pathname translate-pathname
- ed pathname-device truename
- enough-namestring pathname-directory wild-pathname-p
- file-author pathname-host with-open-file
- file-namestring pathname-match-p
-
- Note that many of these functions must accept logical pathnames even though
- they do not accept logical pathname namestrings.
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 23.1.5.3. Using Logical Pathnames
-
- [change_begin]
- Some real file systems do not have versions. Logical pathname translation to
- such a file system ignores the version. This implies that a portable program
- cannot rely on being able to store in a file system more than one version of a
- file named by a logical pathname.
-
- The type of a logical pathname for a Common Lisp source file is LISP. This
- should be translated into whatever implementation-defined type is appropriate
- in a physical pathname.
-
- The logical pathname host name SYS is reserved for the implementation. The
- existence and meaning of logical pathnames for logical host SYS is
- implementation-defined.
-
- File manipulation functions must operate with logical pathnames according to
- the following requirements:
-
- * The following accept logical pathnames and translate them into physical
- pathnames as if by calling the function translate-logical-pathname:
-
- compile-file ed probe-file
- compile-file-pathname file-author rename-file
- delete-file file-write-date truename
- directory load with-open-file
- dribble open
-
- * Applying the function pathname to a stream created by the function open
- or the macro with-open-file using a logical pathname produces a logical
- pathname.
-
- * The functions truename, probe-file, and directory never return logical
- pathnames.
-
- * Calling rename-file with a logical pathname as the second argument
- returns a logical pathname as the first value.
-
- * make-pathname returns a logical pathname if and only if the host is
- logical. If the :host argument to make-pathname is supplied, the host is
- logical if it came from the pathname-host of a logical pathname. Whether a
- :host argument is logical if it is a string equal to a logical pathname
- host name is implementation-defined.
-
- [Function]
- logical-pathname pathname
-
- Converts the argument to a logical pathname and returns it. The argument can be
- a logical pathname, a logical pathname namestring containing a host component,
- or a stream for which the pathname function returns a logical pathname. For any
- other argument, logical-pathname signals an error of type type-error.
-
- [Function]
- translate-logical-pathname pathname &key
-
- Translates a logical pathname to the corresponding physical pathname. The
- pathname argument is first coerced to a pathname. If it is not a pathname,
- string, or file stream, an error of type type-error is signaled.
-
- If the coerced argument is a physical pathname, it is returned.
-
- If the coerced argument is a logical pathname, the first matching translation
- (according to pathname-match-p) of the logical pathname host is applied, as if
- by calling translate-pathname. If the result is a logical pathname, this
- process is repeated. When the result is finally a physical pathname, it is
- returned.
-
- If no translation matches a logical pathname, an error of type file-error is
- signaled.
-
- translate-logical-pathname may perform additional translations, typically to
- provide translation of file types to local naming conventions, to accommodate
- physical file systems with names of limited length, or to deal with special
- character requirements such as translating hyphens to underscores or uppercase
- letters to lowercase. Any such additional translations are
- implementation-defined. Some implementations do no additional translations.
-
- There are no specified keyword arguments for translate-logical-pathname but
- implementations are permitted to extend it by adding keyword arguments. There
- is one specified return value from translate-logical-pathname; implementations
- are permitted to extend it by returning additional values.
-
- [Function]
- logical-pathname-translations host
-
- If the specified host is not the host component of a logical pathname and is
- not a string that has been defined as a logical pathname host name by setf of
- logical-pathname-translations, this function signals an error of type
- type-error; otherwise, it returns the list of translations for the specified
- host. Each translation is a list of at least two elements, from-wildname and
- to-wildname. Any additional elements are implementation-defined. A
- from-wildname is a logical pathname whose host is the specified host. A
- to-wildname is any pathname. Translations are searched in the order listed, so
- more specific from-wildnames must precede more general ones.
-
- (setf (logical-pathname-translations host) translations) sets the list of
- translations for the logical pathname host to translations. If host is a string
- that has not previously been used as logical pathname host, a new logical
- pathname host is defined; otherwise an existing host's translations are
- replaced. Logical pathname host names are compared with string-equal.
-
- When setting the translations list, each from-wildname can be a logical
- pathname whose host is host or a logical pathname namestring s parseable by
- (parse-namestring s host-object), where host-object is an appropriate object
- for representing the specified host to parse-namestring. (This circuitous
- specification dodges the fact that parse-namestring does not necessarily accept
- as its second argument any old string that names a logical host.) Each
- to-wildname can be anything coercible to a pathname by application of the
- function pathname. If to-wildname coerces to a logical pathname,
- translate-logical-pathname will retranslate the result, repeatedly if
- necessary.
-
- Implementations may define additional functions that operate on logical
- pathname hosts (for example, to specify additional translation rules or
- options).
-
- [Function]
- load-logical-pathname-translations host
-
- If a logical pathname host named host (a string) is already defined, this
- function returns nil. Otherwise, it searches for a logical pathname host
- definition in an implementation-defined manner. If none is found, it signals an
- error. If a definition is found, it installs the definition and returns t.
-
- The search used by load-logical-pathname-translations should be documented, as
- logical pathname definitions will be created by users as well as by Lisp
- implementors. A typical search technique is to look in an
- implementation-defined directory for a file whose name is derived from the host
- name in an implementation-defined fashion.
-
- [Function]
- compile-file-pathname pathname &key :output-file
-
- Returns the pathname that compile-file would write into, if given the same
- arguments. If the pathname argument is a logical pathname and the :output-file
- argument is unspecified, the result is a logical pathname. If an implementation
- supports additional keyword arguments to compile-file, compile-file-pathname
- must accept the same arguments.
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 23.1.5.4. Examples of the Use of Logical Pathnames
-
- [change_begin]
- Here is a very simple example of setting up a logical pathname host named FOO.
- Suppose that no translations are necessary to get around file system
- restrictions, so all that is necessary is to specify the root of the physical
- directory tree that contains the logical file system. The namestring syntax in
- the to-wildname is implementation-specific.
-
- (setf (logical-pathname-translations "foo")
- '(("**;*.*.*" "MY-LISPM:>library>foo>**>")))
-
- The following is a sample use of that logical pathname. All return values are
- of course implementation-specific; all of the examples in this section are of
- course meant to be illustrative and not prescriptive.
-
- (translate-logical-pathname "foo:bar;baz;mum.quux.3")
- => #P"MY-LISPM:>library>foo>bar>baz>mum.quux.3"
-
- Next we have a more complex example, dividing the files among two file servers
- (U, supporting a UNIX file system, and V, supporting a VAX/VMS file system) and
- several different directories. This UNIX file system doesn't support
- :wild-inferiors in the directory, so each directory level must be translated
- individually. No file name or type translations are required except for .MAIL
- to .MBX. The namestring syntax used for the to-wildnames is
- implementation-specific.
-
- (setf (logical-pathname-translations "prog")
- '(("RELEASED;*.*.*" "U:/sys/bin/my-prog/")
- ("RELEASED;*;*.*.*" "U:/sys/bin/my-prog/*/")
- ("EXPERIMENTAL;*.*.*"
- "U:/usr/Joe/development/prog/")
- ("EXPERIMENTAL;DOCUMENTATION;*.*.*"
- "V:SYS$DISK:[JOE.DOC]")
- ("EXPERIMENTAL;*;*.*.*"
- "U:/usr/Joe/development/prog/*/")
- ("MAIL;**;*.MAIL" "V:SYS$DISK:[JOE.MAIL.PROG...]*.MBX")
- ))
-
- Here are sample uses of logical host PROG. All return values are of course
- implementation-specific.
-
- (translate-logical-pathname "prog:mail;save;ideas.mail.3")
- => #P"V:SYS$DISK:[JOE.MAIL.PROG.SAVE]IDEAS.MBX.3"
-
- (translate-logical-pathname "prog:experimental;spreadsheet.c")
- => #P"U:/usr/Joe/development/prog/spreadsheet.c"
-
- Suppose now that we have a program that uses three files logically named
- MAIN.LISP, AUXILIARY.LISP, and DOCUMENTATION.LISP. The following translations
- might be provided by a software supplier as examples.
-
- For a UNIX file system with long file names:
-
- (setf (logical-pathname-translations "prog")
- '(("CODE;*.*.*" "/lib/prog/")))
-
- (translate-logical-pathname "prog:code;documentation.lisp")
- => #P"/lib/prog/documentation.lisp"
-
- For a UNIX file system with 14-character file names, using .lisp as the type:
-
- (setf (logical-pathname-translations "prog")
- '(("CODE;DOCUMENTATION.*.*" "/lib/prog/docum.*")
- ("CODE;*.*.*" "/lib/prog/")))
-
- (translate-logical-pathname "prog:code;documentation.lisp")
- => #P"/lib/prog/docum.lisp"
-
- For a UNIX file system with 14-character file names, using .l as the type (the
- second translation shortens the compiled file type to .b):
-
- (setf (logical-pathname-translations "prog")
- `(("**;*.LISP.*" ,(logical-pathname "PROG:**;*.L.*"))
- (,(compile-file-pathname
- (logical-pathname "PROG:**;*.LISP.*"))
- ,(logical-pathname "PROG:**;*.B.*"))
- ("CODE;DOCUMENTATION.*.*" "/lib/prog/documentatio.*")
- ("CODE;*.*.*" "/lib/prog/")))
-
- (translate-logical-pathname "prog:code;documentation.lisp")
- => #P"/lib/prog/documentatio.l"
-
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 23.1.5.5. Discussion of Logical Pathnames
-
- [change_begin]
-
- Large programs can be moved between sites without changing any pathnames,
- provided all pathnames used are logical. A portable system construction tool
- can be created that operates on programs defined as sets of files named by
- logical pathnames.
-
- Logical pathname syntax was chosen to be easily translated into the formats of
- most popular file systems, while still being powerful enough for storing large
- programs. Although they have hierarchical directories, extended wildcard
- matching, versions, and no limit on the length of names, logical pathnames can
- be mapped onto a less capable real file system by translating each directory
- that is used into a flat directory name, processing wildcards in the Lisp
- implementation rather than in the file system, treating all versions as
- :newest, and using translations to shorten long names.
-
- Logical pathname words are restricted to non-case-sensitive letters, digits,
- and hyphens to avoid creating problems with real file systems that support
- limited character sets for file naming. (If logical pathnames were
- case-sensitive, it would be very difficult to map them into a file system that
- is not sensitive to case in its file names.)
-
- It is not a goal of logical pathnames to be able to represent all possible file
- names. Their goal is rather to represent just enough file names to be useful
- for storing software. Real pathnames, in contrast, need to provide a uniform
- interface to all possible file names, including names and naming conventions
- that are not under the control of Common Lisp.
-
- The choice of logical pathname syntax, using colon, semicolon, and period, was
- guided by the goals of being visually distinct from real file systems and
- minimizing the use of special characters.
-
- The logical-pathname function is separate from the pathname function so that
- the syntax of logical pathname namestrings does not constrain the syntax of
- physical pathname namestrings in any way. Logical pathname syntax must be
- defined by Common Lisp so that logical pathnames can be conveniently exchanged
- between implementations, but physical pathname syntax is dictated by the
- operating environments.
-
- The compile-file-pathname function and the specification of LISP as the type of
- a logical pathname for a Common Lisp source file together provide enough
- information about compilation to make possible a portable system construction
- tool. Suppose that it is desirable to call compile-file only if the source file
- is newer than the compiled file. For this to succeed, it must be possible to
- know the name of the compiled file without actually calling compile-file. In
- some implementations the compiler produces one of several file types, depending
- on a variety of implementation-dependent circumstances, so it is not sufficient
- simply to prescribe a standard logical file type for compiled files;
- compile-file-pathname provides access to the defaulting that is performed by
- compile-file ``in a manner appropriate to the implementation's file system
- conventions.''
-
- The use of the logical pathname host name SYS for the implementation is current
- practice. Standardizing on this name helps users choose logical pathname host
- names that avoid conflicting with implementation-defined names.
-
- Loading of logical pathname translations from a site-dependent file allows
- software to be distributed using logical pathnames. The assumed model of
- software distribution is a division of labor between the supplier of the
- software and the user installing it. The supplier chooses logical pathnames to
- name all the files used or created by the software, and supplies examples of
- logical pathname translations for a few popular file systems. Each example uses
- an assumed directory and/or device name, assumes local file naming conventions,
- and provides translations that will translate all the logical pathnames used or
- generated by the particular software into valid physical pathnames. For a
- powerful file system these translations can be quite simple. For a more
- restricted file system, it may be necessary to list an explicit translation for
- every logical pathname used (for example, when dealing with restrictions on the
- maximum length of a file name).
-
- The user installing the software decides on which device and directory to store
- the files and edits the example logical pathname translations accordingly. If
- necessary, the user also adjusts the translations for local file naming
- conventions and any other special aspects of the user's local file system
- policy and local Common Lisp implementation. For example, the files might be
- divided among several file server hosts to share the load. The process of
- defining site-customized logical pathname translations is quite easy for a user
- of a popular file system for which the software supplier has provided an
- example. A user of a more unusual file system might have to take more time; the
- supplier can help by providing a list of all the logical pathnames used or
- generated by the software.Once the user has created and executed a suitable
- setf form for setting the logical-pathname-translations of the relevant logical
- host, the software can be loaded and run. It may be necessary to use the
- translations again, or on another workstation at the same site, so it is best
- to save the setf form in the standard place where it can be found later by
- load-logical-pathname-translations. Often a software supplier will include a
- program for restoring software from the distribution medium to the file system
- and a program for loading the software from the file system into a Common Lisp;
- these programs will start by calling load-logical-pathname-translations to make
- sure that the logical pathname host is defined.
-
- Note that the setf of logical-pathname-translations form isn't part of the
- program; it is separate and is written by the user, not by the software
- supplier. That separation and a uniform convention for doing the separation are
- the key aspects of logical pathnames. For small programs involving only a
- handful of files, it doesn't matter much. The real benefits come with large
- programs with hundreds or thousands of files and more complicated situations
- such as program-generated file names or porting a program developed on a system
- with long file names onto a system with a very restrictive limit on the length
- of file names.
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 23.1.6. Pathname Functions
-
- These functions are what programs use to parse and default file names that have
- been typed in or otherwise supplied by the user.
-
- [old_change_begin]
- Any argument called pathname in this book may actually be a pathname, a string
- or symbol, or a stream. Any argument called defaults may likewise be a
- pathname, a string or symbol, or a stream.
- [old_change_end]
-
- [change_begin]
- X3J13 voted in March 1988 (PATHNAME-SYMBOL) to change the language so that a
- symbol is never allowed as a pathname argument. More specifically, the
- following functions are changed to disallow a symbol as a pathname argument:
-
- pathname pathname-device namestring
- truename pathname-directory file-namestring
- parse-namestring pathname-name directory-namestring
- merge-pathnames pathname-type host-namestring
- pathname-host pathname-version enough-namestring
-
- (The function require was also changed by this vote but was deleted from the
- language by a vote in January 1989 (REQUIRE-PATHNAME-DEFAULTS) .)
- Furthermore, the vote reaffirmed that the following functions do not accept
- symbols as file, filename, or pathname arguments:
-
- open rename-file file-write-date
- with-open-file delete-file file-author
- load probe-file directory
- compile-file
-
- In older implementations of Lisp that did not have strings, for example
- MacLisp, symbols were the only means for specifying pathnames. This was
- convenient only because the file systems of the time allowed only uppercase
- letters in file names. Typing (load 'foo) caused the function load to receive
- the symbol FOO (with uppercase letters because of the way symbols are parsed)
- and therefore to load the file named FOO. Now that many file systems, most
- notably UNIX, support case-sensitive file names, the use of symbols is less
- convenient and more error-prone.
-
- X3J13 voted in March 1988 (PATHNAME-STREAM) to specify that a stream may be
- used as a pathname, file, or filename argument only if it was created by use of
- open or with-open-file, or if it is a synonym stream whose symbol is bound to a
- stream that may be used as a pathname.
-
- If such a stream is used as a pathname, it is as if the pathname function were
- applied to the stream and the resulting pathname used in place of the stream.
- This represents the name used to open the file. This may be, but is not
- required to be, the actual name of the file.
-
- It is an error to attempt to obtain a pathname from a stream created by any of
- the following:
-
- make-two-way-stream make-string-input-stream
- make-echo-stream make-string-output-stream
- make-broadcast-stream with-input-from-string
- make-concatenated-stream with-output-to-string
-
- [change_end]
-
- In the examples, it is assumed that the host named CMUC runs the TOPS-20
- operating system, and therefore uses TOPS-20 file system syntax; furthermore,
- an explicit host name is indicated by following the host name with a double
- colon. Remember, however, that namestring syntax is implementation-dependent,
- and this syntax is used here purely for the sake of examples.
-
- [Function]
- pathname pathname
-
- The pathname function converts its argument to be a pathname. The argument may
- be a pathname, a string or symbol, or a stream; the result is always a
- pathname.
-
- [change_begin]
- X3J13 voted in March 1988 not to permit symbols as pathnames (PATHNAME-SYMBOL)
- and to specify exactly which streams may be used as pathnames
- (PATHNAME-STREAM) .
-
- X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) to specify that
- pathname is unaffected by whether its argument, if a stream, is open or closed.
- X3J13 further commented that because some implementations cannot provide the
- ``true name'' of a file until the file is closed, in such an implementation
- pathname might, in principle, return a different (perhaps more specific) file
- name after the stream is closed. However, such behavior is prohibited; pathname
- must return the same pathname after a stream is closed as it would have while
- the stream was open. See truename.
- [change_end]
-
- [Function]
- truename pathname
-
- The truename function endeavors to discover the ``true name'' of the file
- associated with the pathname within the file system. If the pathname is an open
- stream already associated with a file in the file system, that file is used.
- The ``true name'' is returned as a pathname. An error is signaled if an
- appropriate file cannot be located within the file system for the given
- pathname.
-
- The truename function may be used to account for any file name translations
- performed by the file system, for example.
-
- For example, suppose that DOC: is a TOPS-20 logical device name that is
- translated by the TOPS-20 file system to be PS:<DOCUMENTATION>.
-
- (setq file (open "CMUC::DOC:DUMPER.HLP"))
- (namestring (pathname file)) => "CMUC::DOC:DUMPER.HLP"
- (namestring (truename file))
- => "CMUC::PS:<DOCUMENTATION>DUMPER.HLP.13"
-
- [change_begin]
- X3J13 voted in March 1988 not to permit symbols as pathnames (PATHNAME-SYMBOL)
- and to specify exactly which streams may be used as pathnames
- (PATHNAME-STREAM) .
-
- X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) to specify that
- truename may be applied to a stream whether the stream is open or closed. X3J13
- further commented that because some implementations cannot provide the ``true
- name'' of a file until the file is closed, in principle it would be possible in
- such an implementation for truename to return a different file name after the
- stream is closed. Such behavior is permitted; in this respect truename differs
- from pathname.
-
- X3J13 voted in June 1989 (PATHNAME-WILD) to clarify that truename accepts
- only non-wild pathnames; an error is signaled if wild-pathname-p would be true
- of the pathname argument.
-
- X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require truename to accept
- logical pathnames (see section 23.1.5). However, truename never returns a
- logical pathname.
- [change_end]
-
- [Function]
- parse-namestring thing &optional host defaults &key :start :end :junk-allowed
-
- [old_change_begin]
- This turns thing into a pathname. The thing is usually a string (that is, a
- namestring), but it may be a symbol (in which case the print name is used) or a
- pathname or stream (in which case no parsing is needed, but an error check may
- be made for matching hosts).
- [old_change_end]
-
- [change_begin]
- X3J13 voted in March 1988 not to permit symbols as pathnames (PATHNAME-SYMBOL)
- and to specify exactly which streams may be used as pathnames
- (PATHNAME-STREAM) . The thing argument may not be a symbol.
-
- X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require parse-namestring to
- accept logical pathname namestrings (see section 23.1.5).
- [change_end]
-
- This function does not, in general, do defaulting of pathname components, even
- though it has an argument named defaults; it only does parsing. The host and
- defaults arguments are present because in some implementations it may be that a
- namestring can only be parsed with reference to a particular file name syntax
- of several available in the implementation. If host is non-nil, it must be a
- host name that could appear in the host component of a pathname, or nil; if
- host is nil then the host name is extracted from the default pathname in
- defaults and used to determine the syntax convention. The defaults argument
- defaults to the value of *default-pathname-defaults*.
-
- For a string (or symbol) argument, parse-namestring parses a file name within
- it in the range delimited by the :start and :end arguments (which are integer
- indices into string, defaulting to the beginning and end of the string).
-
- [change_begin]
- See chapter 14 for a discussion of :start and :end arguments.
- [change_end]
-
- If :junk-allowed is not nil, then the first value returned is the pathname
- parsed, or nil if no syntactically correct pathname was seen.
-
- If :junk-allowed is nil (the default), then the entire substring is scanned.
- The returned value is the pathname parsed. An error is signaled if the
- substring does not consist entirely of the representation of a pathname,
- possibly surrounded on either side by whitespace characters if that is
- appropriate to the cultural conventions of the implementation.
-
- In either case, the second value is the index into the string of the delimiter
- that terminated the parse, or the index beyond the substring if the parse
- terminated at the end of the substring (as will always be the case if
- :junk-allowed is false).
-
- If thing is not a string or symbol, then start (which defaults to zero in any
- case) is always returned as the second value.
-
- Parsing an empty string always succeeds, producing a pathname with all
- components (except the host) equal to nil.
-
- Note that if host is specified and not nil, and thing contains a manifest host
- name, an error is signaled if the hosts do not match.
-
- If thing contains an explicit host name and no explicit device name, then it
- might be appropriate, depending on the implementation environment, for
- parse-namestring to supply the standard default device for that host as the
- device component of the resulting pathname.
-
- [Function]
- merge-pathnames pathname &optional defaults default-version
-
- [old_change_begin]
- This is the function that most programs should call to process a file name
- supplied by the user. It fills in unspecified components of pathname from the
- defaults, and returns a new pathname. The pathname and defaults arguments may
- each be a pathname, stream, string, or symbol. The result is always a pathname.
-
- [old_change_end]
-
- [change_begin]
- X3J13 voted in March 1988 not to permit symbols as pathnames (PATHNAME-SYMBOL)
- and to specify exactly which streams may be used as pathnames
- (PATHNAME-STREAM) .
-
- X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require merge-namestrings to
- recognize a logical pathname namestring as its first argument if its second
- argument is a logical pathname (see section 23.1.5).
-
- X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) to specify that
- merge-pathname is unaffected by whether the first argument, if a stream, is
- open or closed. If the first argument is a stream, merge-pathname behaves as if
- the function pathname were applied to the stream and the resulting pathname
- used instead.
-
- X3J13 voted in June 1989 (PATHNAME-COMPONENT-CASE) to require merge-pathnames
- to map customary case in argument pathnames to the customary case in returned
- pathnames (see section 23.1.2).
- [change_end]
-
- defaults defaults to the value of *default-pathname-defaults*.
-
- default-version defaults to :newest.
-
- Here is an example of the use of merge-pathnames:
-
- (merge-pathnames "CMUC::FORMAT"
- "CMUC::PS:<LISPIO>.FASL")
- => a pathname object that re-expressed as a namestring would be
- "CMUC::PS:<LISPIO>FORMAT.FASL.0"
-
- Defaulting of pathname components is done by filling in components taken from
- another pathname. This is especially useful for cases such as a program that
- has an input file and an output file, and asks the user for the name of both,
- letting the unsupplied components of one name default from the other.
- Unspecified components of the output pathname will come from the input
- pathname, except that the type should default not to the type of the input but
- to the appropriate default type for output from this program.
-
- The pathname merging operation takes as input a given pathname, a defaults
- pathname, and a default version, and returns a new pathname. Basically, the
- missing components in the given pathname are filled in from the defaults
- pathname, except that if no version is specified the default version is used.
- The default version is usually :newest; if no version is specified the newest
- version in existence should be used. The default version can be nil, to
- preserve the information that it was missing in the input pathname.
-
- If the given pathname explicitly specifies a host and does not supply a device,
- then if the host component of the defaults matches the host component of the
- given pathname, then the device is taken from the defaults; otherwise the
- device will be the default file device for that host. Next, if the given
- pathname does not specify a host, device, directory, name, or type, each such
- component is copied from the defaults. The merging rules for the version are
- more complicated and depend on whether the pathname specifies a name. If the
- pathname doesn't specify a name, then the version, if not provided, will come
- from the defaults, just like the other components. However, if the pathname
- does specify a name, then the version is not affected by the defaults. The
- reason is that the version ``belongs to'' some other file name and is unlikely
- to have anything to do with the new one. Finally, if this process leaves the
- version missing, the default version is used.
-
- The net effect is that if the user supplies just a name, then the host, device,
- directory, and type will come from the defaults, but the version will come from
- the default version argument to the merging operation. If the user supplies
- nothing, or just a directory, the name, type, and version will come over from
- the defaults together. If the host's file name syntax provides a way to input a
- version without a name or type, the user can let the name and type default but
- supply a version different from the one in the defaults.
-
- [change_begin]
- X3J13 voted in June 1989 (PATHNAME-SYNTAX-ERROR-TIME) to agree to disagree:
- merge-pathname might or might not perform plausibility checking on its
- arguments to ensure that the resulting pathname can be converted a valid
- namestring. User beware: this could cause portability problems.
-
- For example, suppose that host LOSER constrains file types to be three
- characters or fewer but host CMUC does not. Then "LOSER::FORMAT" is a valid
- namestring and "CMUC::PS:<LISPIO>.FASL" is a valid namestring, but
-
- (merge-pathnames "LOSER::FORMAT" "CMUC::PS:<LISPIO>.FASL")
-
- might signal an error in some implementations because the hypothetical result
- would be a pathname equivalent to the namestring "LOSER::FORMAT.FASL" which is
- illegal because the file type FASL has more than three characters. In other
- implementations merge-pathname might return a pathname but that pathname might
- cause namestring to signal an error.
- [change_end]
-
- [Variable]
- *default-pathname-defaults*
-
- This is the default pathname-defaults pathname; if any pathname primitive that
- needs a set of defaults is not given one, it uses this one. As a general rule,
- however, each program should have its own pathname defaults rather than using
- this one.
-
- [old_change_begin]
-
- [Function]
- make-pathname &key :host :device :directory :name :type :version :defaults
-
- Given some components, make-pathname constructs and returns a pathname. After
- the components specified explicitly by the :host, :device, :directory, :name,
- :type, and :version arguments are filled in, the merging rules used by
- merge-pathnames are used to fill in any missing components from the defaults
- specified by the :defaults argument. The default value of the :defaults
- argument is a pathname whose host component is the same as the host component
- of the value of *default-pathname-defaults*, and whose other components are all
- nil.
-
- Whenever a pathname is constructed, whether by make-pathname or some other
- function, the components may be canonicalized if appropriate. For example, if a
- file system is insensitive to case, then alphabetic characters may be forced to
- be all uppercase or all lowercase by the implementation.
- [old_change_end]
-
- [change_begin]
- The following example assumes the use of UNIX syntax and conventions.
-
- (make-pathname :host "technodrome"
- :directory '(:absolute "usr" "krang")
- :name "shredder")
- => #P"technodrome:/usr/krang/shredder"
-
- X3J13 voted in June 1989 (PATHNAME-COMPONENT-CASE) to add a new keyword
- argument :case to make-pathname. The new argument description is therefore as
- follows:
-
- [Function]
- make-pathname &key :host :device :directory :name :type :version :defaults
- :case
-
- See section 23.1.2 for a description of the :case argument.
-
- X3J13 voted in June 1989 (PATHNAME-SYNTAX-ERROR-TIME) to agree to disagree:
- make-pathname might or might not check on its arguments to ensure that the
- resulting pathname can be converted to a valid namestring. If make-pathname
- does not check its arguments and signal an error in problematical cases,
- namestring yet might or might not signal an error when given the resulting
- pathname. User beware: this could cause portability problems.
- [change_end]
-
- [Function]
- pathnamep object
-
- This predicate is true if object is a pathname, and otherwise is false.
-
- (pathnamep x) == (typep x 'pathname)
-
- [old_change_begin]
-
- [Function]
- pathname-host pathname
- pathname-device pathname
- pathname-directory pathname
- pathname-name pathname
- pathname-type pathname
- pathname-version pathname
-
- These return the components of the argument pathname, which may be a pathname,
- string or symbol, or stream. The returned values can be strings, special
- symbols, or some other object in the case of structured components. The type
- will always be a string or a symbol. The version will always be a number or a
- symbol.
- [old_change_end]
-
- [change_begin]
- X3J13 voted in March 1988 not to permit symbols as pathnames (PATHNAME-SYMBOL)
- and to specify exactly which streams may be used as pathnames
- (PATHNAME-STREAM) .
-
- X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) to specify that these
- operations are unaffected by whether the first argument, if a stream, is open
- or closed. If the first argument is a stream, each operation behaves as if the
- function pathname were applied to the stream and the resulting pathname used
- instead.
-
- X3J13 voted in June 1989 (PATHNAME-COMPONENT-CASE) to add a keyword argument
- :case to all of the pathname accessor functions except pathname-version. The
- new argument descriptions are therefore as follows:
-
- [Function]
- pathname-host pathname &key :case
- pathname-device pathname &key :case
- pathname-directory pathname &key :case
- pathname-name pathname &key :case
- pathname-type pathname &key :case
- pathname-version pathname
-
- See section 23.1.2 for a description of the :case argument.
-
- X3J13 voted in June 1989 (PATHNAME-SUBDIRECTORY-LIST) to specify that
- pathname-directory always returns nil, :unspecific, or a list-never a string,
- never :wild (see section 23.1.3). If a list is returned, it is not guaranteed
- to be freshly consed; the consequences of modifying this list are undefined.
- [change_end]
-
- [Function]
- namestring pathname
- file-namestring pathname
- directory-namestring pathname
- host-namestring pathname
- enough-namestring pathname &optional defaults
-
- The pathname argument may be a pathname, a string or symbol, or a stream that
- is or was open to a file. The name represented by pathname is returned as a
- namelist in canonical form.
-
- If pathname is a stream, the name returned represents the name used to open the
- file, which may not be the actual name of the file (see truename).
-
- [change_begin]
- X3J13 voted in March 1988 not to permit symbols as pathnames (PATHNAME-SYMBOL)
- and to specify exactly which streams may be used as pathnames
- (PATHNAME-STREAM) .
-
- X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) to specify that these
- operations are unaffected by whether the first argument, if a stream, is open
- or closed. If the first argument is a stream, each operation behaves as if the
- function pathname were applied to the stream and the resulting pathname used
- instead.
- [change_end]
-
- namestring returns the full form of the pathname as a string. file-namestring
- returns a string representing just the name, type, and version components of
- the pathname; the result of directory-namestring represents just the
- directory-name portion; and host-namestring returns a string for just the
- host-name portion. Note that a valid namestring cannot necessarily be
- constructed simply by concatenating some of the three shorter strings in some
- order.
-
- enough-namestring takes another argument, defaults. It returns an abbreviated
- namestring that is just sufficient to identify the file named by pathname when
- considered relative to the defaults (which defaults to the value of
- *default-pathname-defaults*). That is, it is required that
-
- (merge-pathnames (enough-namestring pathname defaults) defaults) ==
- (merge-pathnames (parse-namestring pathname nil defaults) defaults)
-
- in all cases; and the result of enough-namestring is, roughly speaking, the
- shortest reasonable string that will still satisfy this criterion.
-
- [change_begin]
- X3J13 voted in June 1989 (PATHNAME-SYNTAX-ERROR-TIME) to agree to disagree:
- make-pathname and merge-pathnames might or might not be able to produce
- pathnames that cannot be converted to valid namestrings. User beware: this
- could cause portability problems.
- [change_end]
-
- [Function]
- user-homedir-pathname &optional host
-
- Returns a pathname for the user's ``home directory'' on host. The host argument
- defaults in some appropriate implementation-dependent manner. The concept of
- ``home directory'' is itself somewhat implementation-dependent, but from the
- point of view of Common Lisp it is the directory where the user keeps personal
- files such as initialization files and mail. If it is impossible to determine
- this information, then nil is returned instead of a pathname; however,
- user-homedir-pathname never returns nil if the host argument is not specified.
- This function returns a pathname without any name, type, or version component
- (those components are all nil).
-
- -------------------------------------------------------------------------------
-
- 23.2. Opening and Closing Files
-
- When a file is opened, a stream object is constructed to serve as the file
- system's ambassador to the Lisp environment; operations on the stream are
- reflected by operations on the file in the file system. The act of closing the
- file (actually, the stream) ends the association; the transaction with the file
- system is terminated, and input/output may no longer be performed on the
- stream. The stream function close may be used to close a file; the functions
- described below may be used to open them. The basic operation is open, but
- with-open-file is usually more convenient for most applications.
-
- [Function]
- open filename &key :direction :element-type :if-exists :if-does-not-exist
- :external-format
-
- [change_begin]
- X3J13 voted in June 1989 (MORE-CHARACTER-PROPOSAL) to add to the function
- open a new keyword argument :external-format. This argument did not appear in
- the preceding argument description in the first edition.
- [change_end]
-
- This returns a stream that is connected to the file specified by filename. The
- filename is the name of the file to be opened; it may be a string, a pathname,
- or a stream. (If the filename is a stream, then it is not closed first or
- otherwise affected; it is used merely to provide a file name for the opening of
- a new stream.)
-
- [change_begin]
- X3J13 voted in January 1989 (STREAM-ACCESS) to specify that the result of
- open, if it is a stream, is always a stream of type file-stream.
-
- X3J13 voted in March 1988 (PATHNAME-STREAM) to specify exactly which streams
- may be used as pathnames. See section 23.1.6.
-
- X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) to specify that open
- is unaffected by whether the first argument, if a stream, is open or closed. If
- the first argument is a stream, open behaves as if the function pathname were
- applied to the stream and the resulting pathname used instead.
-
- X3J13 voted in June 1989 (PATHNAME-WILD) to clarify that open accepts only
- non-wild pathnames; an error is signaled if wild-pathname-p would be true of
- filename.
-
- X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require open to accept logical
- pathnames (see section 23.1.5).
- [change_end]
-
- The keyword arguments specify what kind of stream to produce and how to handle
- errors:
-
- :direction
- This argument specifies whether the stream should handle input, output, or
- both.
-
- :input
- The result will be an input stream. This is the default.
-
- :output
- The result will be an output stream.
-
- :io The result will be a bidirectional stream.
-
- :probe
- The result will be a no-directional stream (in effect, the
- stream is created and then closed). This is useful for
- determining whether a file exists without actually setting
- up a complete stream.
-
- :element-type
- This argument specifies the type of the unit of transaction for the
- stream. Anything that can be recognized as being a finite subtype of
- character or integer is acceptable. In particular, the following types are
- recognized:
-
- [old_change_begin]
-
- string-char
- The unit of transaction is a string-character. The
- functions read-char and/or write-char may be used on the
- stream. This is the default.
-
- character
- The unit of transaction is any character, not just a
- string-character. The functions read-char and/or write-char
- may be used on the stream.
-
- [old_change_end]
-
- [change_begin]
- X3J13 voted in June 1989 (MORE-CHARACTER-PROPOSAL) to eliminate the type
- string-char, add the type base-character, and redefine open to use the
- type character as the default :element-type.
-
- The preceding two possibilities should therefore be replaced by the
- following.
-
- character
- The unit of transaction is any character, not just a
- string-character. The functions read-char and write-char
- (depending on the value of the :direction argument) may be
- used on the stream. This is the default.
-
- base-character
- The unit of transaction is a base character. The functions
- read-char and write-char (depending on the value of the
- :direction argument) may be used on the stream.
-
- [change_end]
-
- (unsigned-byte n)
- The unit of transaction is an unsigned byte (a non-negative
- integer) of size n. The functions read-byte and/or
- write-byte may be used on the stream.
-
- unsigned-byte
- The unit of transaction is an unsigned byte (a non-negative
- integer); the size of the byte is determined by the file
- system. The functions read-byte and/or write-byte may be
- used on the stream.
-
- (signed-byte n)
- The unit of transaction is a signed byte of size n. The
- functions read-byte and/or write-byte may be used on the
- stream.
-
- signed-byte
- The unit of transaction is a signed byte; the size of the
- byte is determined by the file system. The functions
- read-byte and/or write-byte may be used on the stream.
-
- bit The unit of transaction is a bit (values 0 and 1). The
- functions read-byte and/or write-byte may be used on the
- stream.
-
- (mod n)
- The unit of transaction is a non-negative integer less than
- n. The functions read-byte and/or write-byte may be used on
- the stream.
-
- :default
- The unit of transaction is to be determined by the file
- system, based on the file it finds. The type can be
- determined by using the function stream-element-type.
-
- :if-exists
- This argument specifies the action to be taken if the :direction is
- :output or :io and a file of the specified name already exists. If the
- direction is :input or :probe, this argument is ignored.
-
- :error
- Signals an error. This is the default when the version
- component of the filename is not :newest.
-
- :new-version
- Creates a new file with the same file name but with a
- larger version number. This is the default when the version
- component of the filename is :newest.
-
- :rename
- Renames the existing file to some other name and then
- creates a new file with the specified name.
-
- :rename-and-delete
- Renames the existing file to some other name and then
- deletes it (but does not expunge it, on those systems that
- distinguish deletion from expunging). Then create a new
- file with the specified name.
-
- :overwrite
- Uses the existing file. Output operations on the stream
- will destructively modify the file. If the :direction is
- :io, the file is opened in a bidirectional mode that allows
- both reading and writing. The file pointer is initially
- positioned at the beginning of the file; however, the file
- is not truncated back to length zero when it is opened.
- This mode is most useful when the file-position function
- can be used on the stream.
-
- :append
- Uses the existing file. Output operations on the stream
- will destructively modify the file. The file pointer is
- initially positioned at the end of the file. If the
- :direction is :io, the file is opened in a bidirectional
- mode that allows both reading and writing.
-
- :supersede
- Supersedes the existing file. If possible, the
- implementation should arrange not to destroy the old file
- until the new stream is closed, against the possibility
- that the stream will be closed in ``abort'' mode (see
- close). This differs from :new-version in that :supersede
- creates a new file with the same name as the old one,
- rather than a file name with a higher version number.
-
- nil Does not create a file or even a stream, but instead simply
- returns nil to indicate failure.
-
- If the :direction is :output or :io and the value of :if-exists is
- :new-version, then the version of the (newly created) file that is opened
- will be a version greater than that of any other file in the file system
- whose other pathname components are the same as those of filename.
-
- If the :direction is :input or :probe or the value of :if-exists is not
- :new-version, and the version component of the filename is :newest, then
- the file opened is that file already existing in the file system that has
- a version greater than that of any other file in the file system whose
- other pathname components are the same as those of filename.
-
- [change_begin]
- Some file systems permit yet other actions to be taken when a file already
- exists; therefore, some implementations provide implementation-specific
- :if-exist options.
- [change_end]
-
- -------------------------------------------------------------------------------
- Implementation note: The various file systems in existence today have widely
- differing capabilities. A given implementation may not be able to support all
- of these options in exactly the manner stated. An implementation is required to
- recognize all of these option keywords and to try to do something
- ``reasonable'' in the context of the host operating system. Implementors are
- encouraged to approximate the semantics specified here as closely as possible.
-
- As an example, suppose that a file system does not support distinct file
- versions and does not distinguish the notions of deletion and expunging (in
- some file systems file deletion is reversible until an expunge operation is
- performed). Then :new-version might be treated the same as :rename or
- :supersede, and :rename-and-delete might be treated the same as :supersede.
-
- If it is utterly impossible for an implementation to handle some option in a
- manner close to what is specified here, it may simply signal an error. The
- opening of files is an area where complete portability is too much to hope for;
- the intent here is simply to make things as portable as possible by providing
- specific names for a range of commonly supportable options.
- -------------------------------------------------------------------------------
-
- :if-does-not-exist
- This argument specifies the action to be taken if a file of the specified
- name does not already exist.
-
- :error
- Signals an error. This is the default if the :direction is
- :input, or if the :if-exists argument is :overwrite or
- :append.
-
- :create
- Creates an empty file with the specified name and then
- proceeds as if it had already existed (but do not perform
- any processing directed by the :if-exists argument). This
- is the default if the :direction is :output or :io, and the
- :if-exists argument is anything but :overwrite or :append.
-
- nil Does not create a file or even a stream, but instead simply
- returns nil to indicate failure. This is the default if the
- :direction is :probe.
-
- [change_begin]
- X3J13 voted in June 1989 (MORE-CHARACTER-PROPOSAL) to add to the function
- open a new keyword argument :external-format.
-
- :external-format
- This argument specifies an implementation-recognized scheme for
- representing characters in files. The default value is :default and is
- implementation-defined but must support the base characters. An error is
- signaled if the implementation does recognize the specified format.
-
- This argument may be specified if the :direction argument is :input,
- :output, or :io. It is an error to write a character to the resulting
- stream that cannot be represented by the specified file format. (However,
- the #\Newline character cannot produce such an error; implementations must
- provide appropriate line division behavior for all character streams.)
-
- See stream-external-format.
-
- [change_end]
-
- When the caller is finished with the stream, it should close the file by using
- the close function. The with-open-file form does this automatically, and so is
- preferred for most purposes. open should be used only when the control
- structure of the program necessitates opening and closing of a file in some way
- more complex than provided by with-open-file. It is suggested that any program
- that uses open directly should use the special form unwind-protect to close the
- file if an abnormal exit occurs.
-
- [Macro]
-
- with-open-file (stream filename {options}*)
- {declaration}* {form}*
-
- with-open-file evaluates the forms of the body (an implicit progn) with the
- variable stream bound to a stream that reads or writes the file named by the
- value of filename. The options are evaluated and are used as keyword arguments
- to the function open.
-
- When control leaves the body, either normally or abnormally (such as by use of
- throw), the file is automatically closed. If a new output file is being
- written, and control leaves abnormally, the file is aborted and the file system
- is left, so far as possible, as if the file had never been opened. Because
- with-open-file always closes the file, even when an error exit is taken, it is
- preferred over open for most applications.
-
- filename is the name of the file to be opened; it may be a string, a pathname,
- or a stream.
-
- [change_begin]
- X3J13 voted in March 1988 (PATHNAME-STREAM) to specify exactly which streams
- may be used as pathnames. See section 23.1.6.
-
- X3J13 voted in June 1989 (PATHNAME-WILD) to clarify that with-open-file
- accepts only non-wild pathnames; an error is signaled if wild-pathname-p would
- be true of the filename argument.
-
- X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require with-open-file to
- accept logical pathnames (see section 23.1.5).
- [change_end]
-
- For example:
-
- (with-open-file (ifile name
- :direction :input)
- (with-open-file (ofile (merge-pathname-defaults ifile
- nil
- "out")
- :direction :output
- :if-exists :supersede)
- (transduce-file ifile ofile)))
-
- [change_begin]
- X3J13 voted in June 1989 (WITH-OPEN-FILE-DOES-NOT-EXIST) to specify that the
- variable stream is not always bound to a stream; rather it is bound to whatever
- would be returned by a call to open. For example, if the options include
- :if-does-not-exist nil, stream will be bound to nil if the file does not exist.
- In this case the value of stream should be tested within the body of the
- with-open-file form before it is used as a stream. For example:
-
- (with-open-file (ifile name
- :direction :input
- :if-does-not-exist nil)
- ;; Process the file only if it actually exists.
- (when (streamp name)
- (compile-cobol-program ifile)))
-
- [change_end]
-
- -------------------------------------------------------------------------------
- Implementation note: While with-open-file tries to automatically close the
- stream on exit from the construct, for robustness it is helpful if the garbage
- collector can detect discarded streams and automatically close them.
- -------------------------------------------------------------------------------
-
- -------------------------------------------------------------------------------
-
- 23.3. Renaming, Deleting, and Other File Operations
-
- These functions provide a standard interface to operations provided in some
- form by most file systems. It may be that some implementations of Common Lisp
- cannot support them all completely.
-
- [Function]
- rename-file file new-name
-
- The specified file is renamed to new-name (which must be a file name). The file
- may be a string, a pathname, or a stream. If it is an open stream associated
- with a file, then the stream itself and the file associated with it are
- affected (if the file system permits).
-
- [change_begin]
- X3J13 voted in March 1988 (PATHNAME-STREAM) to specify exactly which streams
- may be used as pathnames. See section 23.1.6.
- [change_end]
-
- rename-file returns three values if successful. The first value is the new-name
- with any missing components filled in by performing a merge-pathnames operation
- using file as the defaults. The second value is the truename of the file before
- it was renamed. The third value is the truename of the file after it was
- renamed.
-
- If the renaming operation is not successful, an error is signaled.
-
- [old_change_begin]
- It is an error to specify a file name containing a :wild component, for file to
- contain a nil component where the file system does not permit a nil component,
- or for the result of defaulting missing components of new-name from file to
- contain a nil component where the file system does not permit a nil component.
- [old_change_end]
-
- [change_begin]
- X3J13 voted in June 1989 (PATHNAME-WILD) to specify that supplying a wild
- pathname as the file argument to rename-file has implementation-dependent
- consequences; rename-file might signal an error, for example, or might rename
- all files that match the wild pathname.
-
- X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require rename-file to accept
- logical pathnames (see section 23.1.5).
- [change_end]
-
- -------------------------------------------------------------------------------
- Compatibility note: This corresponds to the function called renamef in MacLisp
- and Lisp Machine Lisp. The name renamef is not used in Common Lisp because the
- convention that a trailing f means ``file'' conflicts with the use of a
- trailing f for forms related to setf.
- -------------------------------------------------------------------------------
-
- [Function]
- delete-file file
-
- The specified file is deleted. The file may be a string, a pathname, or a
- stream. If it is an open stream associated with a file, then the stream itself
- and the file associated with it are affected (if the file system permits), in
- which case the stream may or may not be closed immediately, and the deletion
- may be immediate or delayed until the stream is explicitly closed, depending on
- the requirements of the file system.
-
- [change_begin]
- X3J13 voted in March 1988 (PATHNAME-STREAM) to specify exactly which streams
- may be used as pathnames. See section 23.1.6.
- [change_end]
-
- [old_change_begin]
- delete-file returns a non-nil value if successful. It is left to the discretion
- of the implementation whether an attempt to delete a non-existent file is
- considered to be successful. If the deleting operation is not successful, an
- error is signaled.
-
- It is an error to specify a file name that contains a :wild component or one
- that contains a nil component where the file system does not permit a nil
- component.
- [old_change_end]
-
- [change_begin]
- X3J13 voted in June 1989 (PATHNAME-WILD) to clarify that supplying a wild
- pathname as the file argument to delete-file has implementation-dependent
- consequences; delete-file might signal an error, for example, or might delete
- all files that match the wild pathname.
-
- X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require delete-file to accept
- logical pathnames (see section 23.1.5).
- [change_end]
-
- -------------------------------------------------------------------------------
- Compatibility note: This corresponds to the function called deletef in MacLisp
- and Lisp Machine Lisp.
- -------------------------------------------------------------------------------
-
- [Function]
- probe-file file
-
- This predicate is false if there is no file named file, and otherwise returns a
- pathname that is the true name of the file (which may be different from file
- because of file links, version numbers, or other artifacts of the file system).
- Note that if the file is an open stream associated with a file, then probe-file
- cannot return nil but will produce the true name of the associated file. See
- truename and the :probe value for the :direction argument to open.
-
- This corresponds to the function called probef in MacLisp and Lisp Machine
- Lisp.
-
- [change_begin]
- X3J13 voted in March 1988 (PATHNAME-STREAM) to specify exactly which streams
- may be used as pathnames. See section 23.1.6.
-
- X3J13 voted in June 1989 (PATHNAME-WILD) to clarify that probe-file accepts
- only non-wild pathnames; an error is signaled if wild-pathname-p would be true
- of the file argument.
-
- X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require probe-file to accept
- logical pathnames (see section 23.1.5). However, probe-file never returns a
- logical pathname.
-
- X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) to specify that
- probe-file is unaffected by whether the first argument, if a stream, is open or
- closed. If the first argument is a stream, probe-file behaves as if the
- function pathname were applied to the stream and the resulting pathname used
- instead. However, X3J13 further commented that the treatment of open streams
- may differ considerably from one implementation to another; for example, in
- some operating systems open files are written under a temporary or invisible
- name and later renamed when closed. In general, programmers writing code
- intended to be portable should be very careful when using probe-file.
- [change_end]
-
- [Function]
- file-write-date file
-
- file can be a file name or a stream that is open to a file. This returns the
- time at which the file was created or last written as an integer in universal
- time format (see section 25.4.1), or nil if this cannot be determined.
-
- [change_begin]
- X3J13 voted in March 1988 (PATHNAME-STREAM) to specify exactly which streams
- may be used as pathnames. See section 23.1.6.
-
- X3J13 voted in June 1989 (PATHNAME-WILD) to clarify that file-write-date
- accepts only non-wild pathnames; an error is signaled if wild-pathname-p would
- be true of the file argument.
-
- X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require file-write-date to
- accept logical pathnames (see section 23.1.5).
- [change_end]
-
- [Function]
- file-author file
-
- file can be a file name or a stream that is open to a file. This returns the
- name of the author of the file as a string, or nil if this cannot be
- determined.
-
- [change_begin]
- X3J13 voted in March 1988 (PATHNAME-STREAM) to specify exactly which streams
- may be used as pathnames. See section 23.1.6.
-
- X3J13 voted in June 1989 (PATHNAME-WILD) to clarify that file-author accepts
- only non-wild pathnames; an error is signaled if wild-pathname-p would be true
- of the file argument.
-
- X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require file-author to accept
- logical pathnames (see section 23.1.5).
- [change_end]
-
- [Function]
- file-position file-stream &optional position
-
- file-position returns or sets the current position within a random-access file.
-
- (file-position file-stream) returns a non-negative integer indicating the
- current position within the file-stream, or nil if this cannot be determined.
- The file position at the start of a file will be zero. The value returned by
- file-position increases monotonically as input or output operations are
- performed. For a character file, performing a single read-char or write-char
- operation may cause the file position to be increased by more than 1 because of
- character-set translations (such as translating between the Common Lisp
- #\Newline character and an external ASCII carriage-return/line-feed sequence)
- and other aspects of the implementation. For a binary file, every read-byte or
- write-byte operation increases the file position by 1.
-
- (file-position file-stream position) sets the position within file-stream to be
- position. The position may be an integer, or :start for the beginning of the
- stream, or :end for the end of the stream. If the integer is too large or
- otherwise inappropriate, an error is signaled (the file-length function returns
- the length beyond which file-position may not access). An integer returned by
- file-position of one argument should, in general, be acceptable as a second
- argument for use with the same file. With two arguments, file-position returns
- t if the repositioning was performed successfully, or nil if it was not (for
- example, because the file was not random-access).
-
- -------------------------------------------------------------------------------
- Implementation note: Implementations that have character files represented as a
- sequence of records of bounded size might choose to encode the file position
- as, for example, record-number*256+character-within-record. This is a valid
- encoding because it increases monotonically as each character is read or
- written, though not necessarily by 1 at each step. An integer might then be
- considered ``inappropriate'' as a second argument to file-position if, when
- decoded into record number and character number, it turned out that the
- specified record was too short for the specified character number.
- -------------------------------------------------------------------------------
- Compatibility note: This corresponds to the function called filepos in MacLisp
- and Lisp Machine Lisp.
- -------------------------------------------------------------------------------
-
- [Function]
- file-length file-stream
-
- file-stream must be a stream that is open to a file. The length of the file is
- returned as a non-negative integer, or nil if the length cannot be determined.
- For a binary file, the length is specifically measured in units of the
- :element-type specified when the file was opened (see open).
-
- -------------------------------------------------------------------------------
- Compatibility note: This corresponds to the function called lengthf in MacLisp
- and Lisp Machine Lisp.
- -------------------------------------------------------------------------------
-
- [change_begin]
-
- [Function]
- file-string-length file-stream object
-
- X3J13 voted in June 1989 (MORE-CHARACTER-PROPOSAL) to add the function
- file-string-length. The object must be a string or a character. The function
- file-string-length returns a non-negative integer that is the difference
- between what the file-position of the file-stream would be after and before
- writing the object to the file-stream, or nil if this difference cannot be
- determined. The value returned may depend on the current state of the
- file-stream; that is, calling file-string-length on the same arguments twice
- may in certain circumstances produce two different integers.
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 23.4. Loading Files
-
- To load a file is to read through the file, evaluating each form in it.
- Programs are typically stored in files containing calls to constructs such as
- defun, defmacro, and defvar, which define the functions and variables of the
- program.
-
- Loading a compiled (``fasload'') file is similar, except that the file does not
- contain text but rather pre-digested expressions created by the compiler that
- can be loaded more quickly.
-
- [Function]
- load filename &key :verbose :print :if-does-not-exist
-
- This function loads the file named by filename into the Lisp environment. It is
- assumed that a text (character file) can be automatically distinguished from an
- object (binary) file by some appropriate implementation-dependent means,
- possibly by the file type. The defaults for filename are taken from the
- variable *default-pathname-defaults*. If the filename (after the merging in of
- the defaults) does not explicitly specify a type, and both text and object
- types of the file are available in the file system, load should try to select
- the more appropriate file by some implementation-dependent means.
-
- If the first argument is a stream rather than a pathname, then load determines
- what kind of stream it is and loads directly from the stream.
-
- The :verbose argument (which defaults to the value of *load-verbose*), if true,
- permits load to print a message in the form of a comment (that is, with a
- leading semicolon) to *standard-output* indicating what file is being loaded
- and other useful information.
-
- [old_change_begin]
- The :print argument (default nil), if true, causes the value of each expression
- loaded to be printed to *standard-output*. If a binary file is being loaded,
- then what is printed may not reflect precisely the contents of the source file,
- but nevertheless some information will be printed.
- [old_change_end]
-
- [change_begin]
- X3J13 voted in March 1989 (COMPILER-VERBOSITY) to add the variable
- *load-print*; its value is used as the default for the :print argument to load.
-
- The function load rebinds *package* to its current value. If some form in the
- file changes the value of *package* during loading, the old value will be
- restored when the loading is completed. (This was specified in the first
- edition under the description of *package*; for convenience I now mention it
- here as well.)
-
- X3J13 voted in March 1988 (PATHNAME-STREAM) to specify exactly which streams
- may be used as pathnames. See section 23.1.6.
-
- X3J13 voted in June 1989 (PATHNAME-WILD) to clarify that supplying a wild
- pathname as the filename argument to load has implementation-dependent
- consequences; load might signal an error, for example, or might load all files
- that match the pathname.
-
- X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require load to accept logical
- pathnames (see section 23.1.5).
- [change_end]
-
- If a file is successfully loaded, load always returns a non-nil value. If
- :if-does-not-exist is specified and is nil, load just returns nil rather than
- signaling an error if the file does not exist.
-
- [change_begin]
- X3J13 voted in March 1989 (IN-SYNTAX) to require that load bind *readtable*
- to its current value at the time load is called; the dynamic extent of the
- binding should encompass all of the file-loading activity. This allows a
- portable program to include forms such as
-
- (in-package "FOO")
-
- (eval-when (:execute :load-toplevel :compile-toplevel)
- (setq *readtable* foo:my-readtable))
-
- without performing a net global side effect on the loading environment. Such
- statements allow the remainder of such a file to be read either as interpreted
- code or by compile-file in a syntax determined by an alternative readtable.
-
- X3J13 voted in June 1989 (LOAD-TRUENAME) to require that load bind two new
- variables *load-pathname* and *load-truename*; the dynamic extent of the
- bindings should encompass all of the file-loading activity.
- [change_end]
-
- [Variable]
- *load-verbose*
-
- This variable provides the default for the :verbose argument to load. Its
- initial value is implementation-dependent.
-
- [change_begin]
-
- [Variable]
- *load-print*
-
- X3J13 voted in March 1989 (COMPILER-VERBOSITY) to add *load-print*. This
- variable provides the default for the :print argument to load. Its initial
- value is nil.
-
- [Variable]
- *load-pathname*
-
- X3J13 voted in June 1989 (LOAD-TRUENAME) to introduce *load-pathname*; it is
- initially nil but load binds it to a pathname that represents the file name
- given as the first argument to load merged with the defaults (see
- merge-pathname).
-
- [Variable]
- *load-truename*
-
- X3J13 voted in June 1989 (LOAD-TRUENAME) to introduce *load-truename*; it is
- initially nil but load binds it to the ``true name'' of the file being loaded.
- See truename.
-
- X3J13 voted in March 1989 (LOAD-OBJECTS) to introduce a facility based on the
- Object System whereby a user can specify how compile-file and load must
- cooperate to reconstruct compile-time constant objects at load time. The
- protocol is simply this: compile-file calls the generic function make-load-form
- on any object that is referenced as a constant or as a self-evaluating form, if
- the object's metaclass is standard-class, structure-class, any user-defined
- metaclass (not a subclass of built-in-class), or any of a possibly empty
- implementation-defined list of other metaclasses; compile-file will call
- make-load-form only once for any given object (as determined by eq) within a
- single file. The user-programmability stems from the possibility of
- user-defined methods for make-load-form. The helper function
- make-load-form-saving-slots makes it easy to write commonly used versions of
- such methods.
-
- [Generic function]
- make-load-form object
-
- The argument is an object that is referenced as a constant or as a
- self-evaluating form in a file being compiled by compile-file. The objective is
- to enable load to construct an equivalent object.
-
- The first value, called the creation form, is a form that, when evaluated at
- load time, should return an object that is equivalent to the argument. The
- exact meaning of ``equivalent'' depends on the type of object and is up to the
- programmer who defines a method for make-load-form. This allows the user to
- program the notion of ``similar as a constant'' (see section 25.1).
-
- The second value, called the initialization form, is a form that, when
- evaluated at load time, should perform further initialization of the object.
- The value returned by the initialization form is ignored. If the make-load-form
- method returns only one value, the initialization form is nil, which has no
- effect. If the object used as the argument to make-load-form appears as a
- constant in the initialization form, at load time it will be replaced by the
- equivalent object constructed by the creation form; this is how the further
- initialization gains access to the object.
-
- Two values are returned so that circular structures may be handled. The order
- of evaluation rules discussed below for creation and initialization forms
- eliminates the possibility of partially initialized objects in the absence of
- circular structures and reduces the possibility to a minimum in the presence of
- circular structures. This allows nodes in non-circular structures to be built
- out of fully initialized subparts.
-
- Both the creation form and the initialization form can contain references to
- objects of user-defined types (defined precisely below). However, there must
- not be any circular dependencies in creation forms. An example of a circular
- dependency: the creation form for the object X contains a reference to the
- object Y, and the creation form for the object Y contains a reference to the
- object X. A simpler example: the creation form for the object X contains a
- reference to X itself. Initialization forms are not subject to any restriction
- against circular dependencies, which is the entire reason for having
- initialization forms. See the example of circular data structures below.
-
- The creation form for an object is always evaluated before the initialization
- form for that object. When either the creation form or the initialization form
- refers to other objects of user-defined types that have not been referenced
- earlier in the compile-file, the compiler collects all of the creation and
- initialization forms. Each initialization form is evaluated as soon as possible
- after its creation form, as determined by data flow. If the initialization form
- for an object does not refer to any other objects of user-defined types that
- have not been referenced earlier in the compile-file, the initialization form
- is evaluated immediately after the creation form. If a creation or
- initialization form F references other objects of user-defined types that have
- not been referenced earlier in the compile-file, the creation forms for those
- other objects are evaluated before F and the initialization forms for those
- other objects are also evaluated before F whenever they do not depend on the
- object created or initialized by F. Where the above rules do not uniquely
- determine an order of evaluation, it is unspecified which of the possible
- orders of evaluation is chosen.
-
- While these creation and initialization forms are being evaluated, the objects
- are possibly in an uninitialized state, analogous to the state of an object
- between the time it has been created by allocate-instance and it has been
- processed fully by initialize-instance. Programmers writing methods for
- make-load-form must take care in manipulating objects not to depend on slots
- that have not yet been initialized.
-
- It is unspecified whether load calls eval on the forms or does some other
- operation that has an equivalent effect. For example, the forms might be
- translated into different but equivalent forms and then evaluated; they might
- be compiled and the resulting functions called by load (after they themselves
- have been loaded); or they might be interpreted by a special-purpose
- interpreter different from eval. All that is required is that the effect be
- equivalent to evaluating the forms.
-
- It is valid for user programs to call make-load-form in circumstances other
- than compilation, providing the argument's metaclass is not built-in-class or a
- subclass of built-in-class.
-
- Applying make-load-form to an object whose metaclass is standard-class or
- structure-class for which no user-defined method is applicable signals an
- error. It is valid to implement this either by defining default methods for the
- classes standard-object and structure-object that signal an error or by having
- no applicable method for those classes.
-
- See load-time-eval.
-
- In the following example, an equivalent instance of my-class is reconstructed
- by using the values of two of its slots. The value of the third slot is derived
- from those two values.
-
- (defclass my-class ()
- ((a :initarg :a :reader my-a)
- (b :initarg :b :reader my-b)
- (c :accessor my-c)))
-
- (defmethod shared-initialize ((self my-class) slots &rest inits)
- (declare (ignore slots inits))
- (unless (slot-boundp self 'c)
- (setf (my-c self)
- (some-computation (my-a self) (my-b self)))))
-
- (defmethod make-load-form ((self my-class))
- `(make-instance ',(class-name (class-of self))
- :a ',(my-a self) :b ',(my-b self)))
-
- This code will fail if either of the first two slots of some instance of
- my-class contains the instance itself. Another way to write the last form in
- the preceding example is
-
- (defmethod make-load-form ((self my-class))
- (make-load-form-saving-slots self '(a b)))
-
- This has the advantages of conciseness and handling circularities correctly.
-
- In the next example, instances of class my-frob are ``interned'' in some way.
- An equivalent instance is reconstructed by using the value of the name slot as
- a key for searching for existing objects. In this case the programmer has
- chosen to create a new object if no existing object is found; an alternative
- possibility would be to signal an error in that case.
-
- (defclass my-frob ()
- ((name :initarg :name :reader my-name)))
-
- (defmethod make-load-form ((self my-frob))
- `(find-my-frob ',(my-name self) :if-does-not-exist :create))
-
- In the following example, the data structure to be dumped is circular, because
- each node of a tree has a list of its children and each child has a reference
- back to its parent.
-
- (defclass tree-with-parent () ((parent :accessor tree-parent)
- (children :initarg :children)))
-
- (defmethod make-load-form ((x tree-with-parent))
- (values
- `(make-instance ',(class-of x)
- :children ',(slot-value x 'children))
- `(setf (tree-parent ',x) ',(slot-value x 'parent))))
-
- Suppose make-load-form is called on one object in such a structure. The
- creation form creates an equivalent object and fills in the children slot,
- which forces creation of equivalent objects for all of its children,
- grandchildren, etc. At this point none of the parent slots have been filled in.
- The initialization form fills in the parent slot, which forces creation of an
- equivalent object for the parent if it was not already created. Thus the entire
- tree is recreated at load time. At compile time, make-load-form is called once
- for each object in the tree. All the creation forms are evaluated, in
- unspecified order, and then all the initialization forms are evaluated, also in
- unspecified order.
-
- In this final example, the data structure to be dumped has no special
- properties and an equivalent structure can be reconstructed simply by
- reconstructing the slots' contents.
-
- (defstruct my-struct a b c)
-
- (defmethod make-load-form ((s my-struct))
- (make-load-form-saving-slots s))
-
- This is easy to code using make-load-form-saving-slots.
-
- [Function]
- make-load-form-saving-slots object &optional slots
-
- This returns two values suitable for return from a make-load-form method. The
- first argument is the object. The optional second argument is a list of the
- names of slots to preserve; it defaults to all of the local slots.
-
- make-load-form-saving-slots returns forms that construct an equivalent object
- using make-instance and setf of slot-value for slots with values, or
- slot-makunbound for slots without values, or other functions of equivalent
- effect.
-
- Because make-load-form-saving-slots returns two values, it can deal with
- circular structures; it works for any object of metaclass standard-class or
- structure-class. Whether the result is useful depends on whether the object's
- type and slot contents fully capture an application's idea of the object's
- state.
- [change_end]
-
- -------------------------------------------------------------------------------
-
- 23.5. Accessing Directories
-
- The following function is a very simple portable primitive for examining a
- directory. Most file systems can support much more powerful directory-searching
- primitives, but no two are alike. It is expected that most implementations of
- Common Lisp will extend the directory function or provide more powerful
- primitives.
-
- [Function]
- directory pathname &key
-
- A list of pathnames is returned, one for each file in the file system that
- matches the given pathname. (The pathname argument may be a pathname, a string,
- or a stream associated with a file.) For a file that matches, the truename
- appears in the result list. If no file matches the pathname, it is not an
- error; directory simply returns nil, the list of no results. Keywords such as
- :wild and :newest may be used in pathname to indicate the search space.
-
- [change_begin]
- X3J13 voted in March 1988 (PATHNAME-STREAM) to specify exactly which streams
- may be used as pathnames. See section 23.1.6.
-
- X3J13 voted in January 1989 (CLOSED-STREAM-OPERATIONS) to specify that
- directory is unaffected by whether the first argument, if a stream, is open or
- closed. If the first argument is a stream, directory behaves as if the function
- pathname were applied to the stream and the resulting pathname used instead.
- However, X3J13 commented that the treatment of open streams may differ
- considerably from one implementation to another; for example, in some operating
- systems open files are written under a temporary or invisible name and later
- renamed when closed. In general, programmers writing code intended to be
- portable should be careful when using directory.
-
- X3J13 voted in June 1989 (PATHNAME-LOGICAL) to require directory to accept
- logical pathnames (see section 23.1.5). However, the result returned by
- directory never contains a logical pathname.
- [change_end]
-
- -------------------------------------------------------------------------------
- Implementation note: It is anticipated that an implementation may need to
- provide additional parameters to control the directory search. Therefore
- directory is specified to take additional keyword arguments so that
- implementations may experiment with extensions, even though no particular
- keywords are specified here.
-
- As a simple example of such an extension, for a file system that supports the
- notion of cross-directory file links, a keyword argument :links might, if
- non-nil, specify that such links be included in the result list.
- -------------------------------------------------------------------------------
-
- -------------------------------------------------------------------------------
-
-
-
-
-
-
-